home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume14 / dmake / part18 < prev    next >
Encoding:
Text File  |  1990-07-26  |  39.1 KB  |  1,532 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v14i028: dmake version 3.5 part 18/21
  3. From: dvadura@watdragon.waterloo.edu (Dennis Vadura)
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 14, Issue 28
  7. Submitted-by: dvadura@watdragon.waterloo.edu (Dennis Vadura)
  8. Archive-name: dmake/part18
  9.  
  10. #!/bin/sh
  11. # this is part 18 of a multipart archive
  12. # do not concatenate these parts, unpack them in order with /bin/sh
  13. # file dmake.c continued
  14. #
  15. CurArch=18
  16. if test ! -r s2_seq_.tmp
  17. then echo "Please unpack part 1 first!"
  18.      exit 1; fi
  19. ( read Scheck
  20.   if test "$Scheck" != $CurArch
  21.   then echo "Please unpack part $Scheck next!"
  22.        exit 1;
  23.   else exit 0; fi
  24. ) < s2_seq_.tmp || exit 1
  25. echo "x - Continuing file dmake.c"
  26. sed 's/^X//' << 'SHAR_EOF' >> dmake.c
  27. X   ex_val = Target;     /* make sure we don't mark any        */
  28. X   Target = TRUE;       /* of the default rules as            */
  29. X   Make_rules();        /* potential targets                  */
  30. X   _warn = TRUE;
  31. X
  32. X   if( Rules ) {
  33. X      /* order of precedence is:
  34. X       *
  35. X       *   MAKESTARTUP  from command line (precious is marked)
  36. X       *   MAKESTARTUP  from environment
  37. X       *   MAKESTARTUP  from builtin rules (not precious)
  38. X       */
  39. X      char *fname;
  40. X
  41. X      if( ((hp = GET_MACRO("MAKESTARTUP")) != NIL(HASH)) &&
  42. X      (hp->ht_flag & M_PRECIOUS) &&
  43. X      (mkfil=Openfile(fname=hp->ht_value, FALSE)) != NIL(FILE) ||
  44. X      (mkfil=Openfile(fname=Read_env_string("MAKESTARTUP"), FALSE)) != NIL(FILE) ||
  45. X      hp != NIL(HASH) &&
  46. X      (mkfil=Openfile(fname=hp->ht_value, FALSE)) != NIL(FILE) )
  47. X      {
  48. X         Parse(mkfil);
  49. X         mkfil = NIL(FILE);
  50. X      }
  51. X      else
  52. X         Fatal( "configuration file `%s' not found", fname );
  53. X   }
  54. X
  55. X   Target = ex_val;
  56. X
  57. X   if( Get_env == 'e' ) _do_ReadEnvironment();
  58. X
  59. X   if( fil_name != NIL(char) )
  60. X      mkfil = Openfile( fil_name, TRUE );
  61. X   else {
  62. X      /* Search .MAKEFILES dependent list looking for a makefile.
  63. X       */
  64. X      register CELLPTR cp;
  65. X      register LINKPTR lp;
  66. X
  67. X      cp = Def_cell( ".MAKEFILES", NIL(CELL) );
  68. X
  69. X      if( (lp = cp->CE_PRQ) != NIL(LINK) ) {
  70. X         int s_n, s_t, s_q;
  71. X
  72. X         s_n = Trace;
  73. X         s_t = Touch;
  74. X         s_q = Check;
  75. X
  76. X         Trace = Touch = Check = FALSE;
  77. X         Makemkf = Wait_for_completion = TRUE;
  78. X         mkfil = NIL(FILE);
  79. X
  80. X         for(;  lp != NIL(LINK) && mkfil == NIL(FILE); lp=lp->cl_next) {
  81. X            mkfil = Openfile( lp->cl_prq->CE_NAME, FALSE );
  82. X
  83. X            if( mkfil == NIL(FILE) &&
  84. X        Make(lp->cl_prq, lp->cl_prq->CE_HOW, NIL(CELL)) != -1 )
  85. X               mkfil = Openfile( lp->cl_prq->CE_NAME, FALSE );
  86. X         }
  87. X
  88. X         Trace = s_n;
  89. X         Touch = s_t;
  90. X         Check = s_q;
  91. X         Makemkf = Wait_for_completion = FALSE;
  92. X      }
  93. X   }
  94. X
  95. X   if( mkfil != NIL(FILE) ) {
  96. X      char *f = Filename();
  97. X      char *p;
  98. X
  99. X      if( strcmp(f, "stdin") == 0 ) f = "-";
  100. X      p = _stradd( "-f", f, FALSE );
  101. X      Def_macro( "MAKEFILE", p, M_PRECIOUS|M_NOEXPORT );
  102. X      Parse( mkfil );
  103. X   }
  104. X   else if( !Rules )
  105. X      Fatal( "No `makefile' present" );
  106. X
  107. X   if( Nest_level     ) Fatal( "Missing .END for .IF" );
  108. X   if( Get_env == 'E' ) _do_ReadEnvironment();
  109. X
  110. X   _do_VPATH();                  /* kludge it up with .SOURCE    */
  111. X
  112. X   if( Listing ) Dump();        /* print out the structures     */
  113. X   if( Trace ) Glob_attr &= ~A_SILENT;    /* make sure we see the trace   */
  114. X
  115. X   if( !Target )
  116. X      Fatal( "No target" );
  117. X   else {
  118. X      Check_circle( Fringe_hd );
  119. X      Check_circle_dfa();
  120. X   }
  121. X
  122. X   TALLOC( Start_dir.ce_name, 1, HASH );
  123. X   Start_dir.CE_NAME = ".SETDIR";
  124. X   Push_dir( &Start_dir, Glob_attr & A_IGNORE );
  125. X
  126. X   if( m_export ) {
  127. X      int i;
  128. X
  129. X      for( i=0; i<HASH_TABLE_SIZE; ++i ) {
  130. X         char *tmpstr = hp->ht_value;
  131. X
  132. X         if( tmpstr == NIL(char) ) tmpstr = "";
  133. X         if( !(hp->ht_flag & M_NOEXPORT) &&
  134. X         Write_env_string(hp->ht_name, tmpstr) != 0 )
  135. X            Warning( "Could not export %s", hp->ht_name );
  136. X      }
  137. X   }
  138. X   if( Buffer != NIL(char) ) FREE( Buffer );
  139. X   if( Trace ) Def_macro(".SEQUENTIAL", "y", M_EXPANDED);
  140. X   if( Glob_attr & A_SEQ ) Def_macro( "MAXPROCESS", "1", M_EXPANDED|M_FORCE );
  141. X
  142. X   ex_val = Make_targets();
  143. X
  144. X   Pop_dir( Glob_attr & A_IGNORE );
  145. X   Clear_signals();
  146. X   Epilog(ex_val);      /* Does not return -- EVER */
  147. X}
  148. X
  149. X
  150. Xstatic void
  151. X_do_ReadEnvironment()
  152. X{
  153. X   int saveattr = Glob_attr;
  154. X
  155. X   Glob_attr |= A_SILENT;
  156. X   ReadEnvironment();
  157. X   Glob_attr = saveattr;
  158. X}
  159. X
  160. X
  161. Xstatic void
  162. X_do_VPATH()
  163. X{
  164. X   HASHPTR hp;
  165. X   char    *_rl[2];
  166. X   extern char **Rule_tab;
  167. X
  168. X   hp = GET_MACRO("VPATH");
  169. X   if( hp == NIL(HASH) ) return;
  170. X
  171. X   _rl[0] = ".SOURCE :^ $(VPATH:s/:/ /)";
  172. X   _rl[1] = NIL(char);
  173. X
  174. X   Rule_tab = _rl;
  175. X   Parse( NIL(FILE) );
  176. X}
  177. X
  178. X
  179. X/*  The file table and pointer to the next FREE slot for use by both
  180. X    Openfile and Closefile.  Each open stacks the new file onto the open
  181. X    file stack, and a corresponding close will close the passed file, and
  182. X    return the next file on the stack.  The maximum number of nested
  183. X    include files is limited by the value of MAX_INC_DEPTH */
  184. X
  185. Xstatic struct {
  186. X   FILE         *file;      /* file pointer                 */
  187. X   char         *name;      /* name of file                 */
  188. X   int          numb;       /* line number                  */
  189. X} ftab[ MAX_INC_DEPTH ];
  190. X
  191. Xstatic int next_file_slot = 0;
  192. X
  193. X/* Set the proper macro value to reflect the depth of the .INCLUDE directives.
  194. X */
  195. Xstatic void
  196. X_set_inc_depth()
  197. X{
  198. X   char buf[10];
  199. X   sprintf( buf, "%d", next_file_slot-1 );
  200. X   Def_macro( "INCDEPTH", buf, M_MULTI|M_NOEXPORT );
  201. X}
  202. X
  203. X
  204. XFILE *
  205. XOpenfile(name, err)/*
  206. X=====================
  207. X   This routine opens a file for input.
  208. X   If the file name is `-' then it returns standard input.
  209. X   The file is pushed onto the open file stack.  */
  210. Xchar *name;
  211. Xint  err;
  212. X{
  213. X   FILE *fil;
  214. X
  215. X   DB_ENTER("Openfile");
  216. X
  217. X   if( name == NIL(char) || !*name )
  218. X      if( !err )
  219. X         DB_RETURN(NIL(FILE));
  220. X      else
  221. X         Fatal( "Openfile:  NIL filename" );
  222. X   
  223. X   if( next_file_slot == MAX_INC_DEPTH )
  224. X      Fatal( "Too many open files. Max nesting level is %d.", MAX_INC_DEPTH);
  225. X
  226. X   DB_PRINT( "io", ("Opening file [%s], in slot %d", name, next_file_slot) );
  227. X
  228. X   if( strcmp("-", name) == 0 ) {
  229. X      name = "stdin";
  230. X      fil = stdin;
  231. X   }
  232. X   else
  233. X      fil = fopen( name, "r" );
  234. X
  235. X   if( fil == NIL(FILE) ) {
  236. X      if( err )
  237. X         Fatal( "File %s not found", name );
  238. X   }
  239. X   else {
  240. X      ftab[next_file_slot].file   = fil;
  241. X      ftab[next_file_slot].numb   = Line_number;
  242. X      ftab[next_file_slot++].name = _strdup(name);
  243. X      Line_number = 0;
  244. X      _set_inc_depth();
  245. X   }
  246. X
  247. X   DB_RETURN(fil);
  248. X}
  249. X
  250. XFILE *
  251. XClosefile()/*
  252. X=============
  253. X   This routine is used to close the last file opened.  This forces make
  254. X   to open files in a last open first close fashion.  It returns the
  255. X   file pointer to the next file on the stack, and NULL if the stack is empty.*/
  256. X{
  257. X   DB_ENTER("Closefile");
  258. X
  259. X   if( !next_file_slot )
  260. X      DB_RETURN( NIL(FILE) );
  261. X
  262. X   if( ftab[--next_file_slot].file != stdin ) {
  263. X      DB_PRINT( "io", ("Closing file in slot %d", next_file_slot) );
  264. X      fclose( ftab[next_file_slot].file );
  265. X      FREE( ftab[next_file_slot].name );
  266. X      _set_inc_depth();
  267. X   }
  268. X
  269. X   if( next_file_slot > 0 ) {
  270. X      Line_number = ftab[next_file_slot].numb;
  271. X      DB_RETURN( ftab[next_file_slot-1].file );
  272. X   }
  273. X   else
  274. X      Line_number = 0;
  275. X
  276. X   DB_RETURN( NIL(FILE) );
  277. X}
  278. X
  279. X
  280. Xchar *
  281. XFilename()/*
  282. X============
  283. X   Return name of file on top of stack */
  284. X{
  285. X   return( next_file_slot==0 ? NIL(char) : ftab[next_file_slot-1].name );
  286. X}
  287. X
  288. X/*
  289. X** print error message from variable arg list
  290. X*/
  291. X
  292. Xstatic int errflg = TRUE;
  293. Xstatic int warnflg = FALSE;
  294. X
  295. Xstatic void
  296. Xerrargs(fmt, args)
  297. Xchar    *fmt;
  298. Xva_list  args;
  299. X{
  300. X   int warn = _warn && warnflg && !(Glob_attr & A_SILENT);
  301. X
  302. X   if( errflg || warn ) {
  303. X      char *f = Filename();
  304. X
  305. X      fprintf( stderr, "%s:  ", Pname );
  306. X      if( f != NIL(char) ) fprintf(stderr, "%s:  line %d:  ", f, Line_number);
  307. X
  308. X      if( errflg )
  309. X         fprintf(stderr, "Error -- ");
  310. X      else if( warn )
  311. X         fprintf(stderr, "Warning -- ");
  312. X
  313. X      vfprintf( stderr, fmt, args );
  314. X      putc( '\n', stderr );
  315. X      if( errflg && !Continue ) Quit( NIL(CELL) );
  316. X   }
  317. X}
  318. X
  319. X/*
  320. X** Print error message and abort
  321. X*/
  322. Xint
  323. XFatal(fmt, va_alist)
  324. Xchar *fmt;
  325. Xva_dcl;
  326. X{
  327. X   va_list args;
  328. X
  329. X   va_start(args, fmt);
  330. X   Continue = FALSE;
  331. X   errargs(fmt, args);
  332. X   va_end(args);
  333. X}
  334. X
  335. X/*
  336. X** error message and exit (unless -k)
  337. X*/
  338. Xint
  339. XError(fmt, va_alist)
  340. Xchar*   fmt;
  341. Xva_dcl;
  342. X{
  343. X   va_list args;
  344. X
  345. X   va_start(args, fmt);
  346. X   errargs(fmt, args);
  347. X   va_end(args);
  348. X}
  349. X
  350. X
  351. X/*
  352. X** non-fatal message
  353. X*/
  354. Xint
  355. XWarning(fmt, va_alist)
  356. Xchar *fmt;
  357. Xva_dcl;
  358. X{
  359. X   va_list args;
  360. X
  361. X   va_start(args, fmt);
  362. X   warnflg = TRUE;
  363. X   errflg = FALSE;
  364. X   errargs(fmt, args);
  365. X   errflg = TRUE;
  366. X   warnflg = FALSE;
  367. X   va_end(args);
  368. X}
  369. X
  370. X
  371. Xvoid
  372. XNo_ram()
  373. X{
  374. X   Fatal( "No more memory" );
  375. X}
  376. X
  377. X
  378. X#ifdef HELP
  379. XUsage()
  380. X{
  381. X   printf(USAGE, Pname);
  382. X   puts("    -P#       - set max number of child processes for parallel make");
  383. X   puts("    -f file   - use file as the makefile\n");
  384. X
  385. X   puts("OPTIONS: (can be catenated, ie -irn == -i -r -n)");
  386. X   puts("    -A   - enable AUGMAKE special target mapping");
  387. X   puts("    -e   - define environment strings as macros");
  388. X   puts("    -E   - same as -e but done after parsing makefile");
  389. X   puts("    -h   - print out usage info");
  390. X   puts("    -i   - ignore errors");
  391. X   puts("    -k   - make independent targets, even if errors");
  392. X   puts("    -n   - trace and print, do not execute commands");
  393. X   puts("    -p   - print out a version of the makefile");
  394. X   puts("    -q   - check if target is up to date.  Does not do");
  395. X   puts("           anything.  Returns 0 if up to date, 1 otherwise");
  396. X   puts("    -r   - don't use internal rules");
  397. X   puts("    -s   - do your work silently");
  398. X   puts("    -S   - disable parallel (force sequential) make, overrides -P");
  399. X   puts("    -t   - touch, update time stamps without executing commands");
  400. X   puts("    -T   - do not apply transitive closure");
  401. X   puts("    -u   - force unconditional update of target");
  402. X   puts("    -v   - verbose, print out what we are doing");
  403. X   puts("    -V   - print out version number");
  404. X   puts("    -x   - export macro values to environment");
  405. X
  406. X   /*** The feature below is disabled for now */
  407. X   /*puts("    -M   - Microsoft MAKE compatibility");*/
  408. X}
  409. X#endif
  410. X
  411. X
  412. XVersion()
  413. X{
  414. X   extern char **Rule_tab;
  415. X   char **p;
  416. X   
  417. X   printf("%s - %s, ", Pname, COPYRIGHT);
  418. X   printf("Version %s, Patch Level %d\n\n", VERSION, PATCHLEVEL);
  419. X
  420. X   puts("Default Configuration:");
  421. X   for (p=Rule_tab;  *p != NIL(char);  p++)
  422. X      printf("\t%s\n", *p);
  423. X}
  424. SHAR_EOF
  425. echo "File dmake.c is complete"
  426. chmod 0440 dmake.c || echo "restore of dmake.c fails"
  427. echo "x - extracting dag.c (Text)"
  428. sed 's/^X//' << 'SHAR_EOF' > dag.c &&
  429. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/RCS/dag.c,v 1.1 90/07/19 13:53:02 dvadura Exp $
  430. X-- SYNOPSIS -- Routines to construct the internal dag.
  431. X-- 
  432. X-- DESCRIPTION
  433. X--    This file contains all the routines that are responsible for
  434. X--    defining and manipulating all objects used by the make facility.
  435. X-- 
  436. X-- AUTHOR
  437. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  438. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  439. X--
  440. X-- COPYRIGHT
  441. X--      Copyright (c) 1990 by Dennis Vadura.  All rights reserved.
  442. X-- 
  443. X--      This program is free software; you can redistribute it and/or
  444. X--      modify it under the terms of the GNU General Public License
  445. X--      (version 1), as published by the Free Software Foundation, and
  446. X--      found in the file 'LICENSE' included with this distribution.
  447. X-- 
  448. X--      This program is distributed in the hope that it will be useful,
  449. X--      but WITHOUT ANY WARRANTY; without even the implied warrant of
  450. X--      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  451. X--      GNU General Public License for more details.
  452. X-- 
  453. X--      You should have received a copy of the GNU General Public License
  454. X--      along with this program;  if not, write to the Free Software
  455. X--      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  456. X--
  457. X-- LOG
  458. X--     $Log:    dag.c,v $
  459. X * Revision 1.1  90/07/19  13:53:02  dvadura
  460. X * Initial Revision of Version 3.5
  461. X * 
  462. X*/
  463. X
  464. X#include <ctype.h>
  465. X#include "extern.h"
  466. X#include "alloc.h"
  467. X#include "db.h"
  468. X
  469. X
  470. XHASHPTR
  471. XGet_name( name, tab, define, dir )/*
  472. X====================================
  473. X    Look to see if the name is defined, if it is then return
  474. X    a pointer to its node, if not return NIL(HASH).
  475. X    If define is TRUE and the name is not found it will be added. */
  476. X
  477. Xchar    *name;            /* name we are looking for   */
  478. XHASHPTR *tab;            /* the hash table to look in */
  479. Xint    define;            /* TRUE => add to table      */
  480. XCELLPTR dir;
  481. X{
  482. X   register HASHPTR hp;
  483. X   register char    *p;
  484. X   uint16           hv;
  485. X   uint32           hash_key;
  486. X
  487. X   DB_ENTER( "Get_name" );
  488. X   DB_PRINT( "name", ("Looking for %s", name) );
  489. X
  490. X   hv = Hash( name, &hash_key );
  491. X
  492. X   for( hp = tab[ hv ]; hp != NIL(HASH); hp = hp->ht_next )
  493. X      if( hp->ht_hash == hash_key &&
  494. X      (tab != Defs || ((tab == Defs) && (hp->CP_ROOT == dir))) &&
  495. X      !strcmp(hp->ht_name, name) )
  496. X         break;
  497. X
  498. X   if( hp == NIL(HASH) && define ) {
  499. X      /* Check to make sure that CELL name contains only printable chars */
  500. X      for( p=name; *p; p++ )
  501. X     if( !isprint(*p) )
  502. X        Fatal( "Name contains non-printable character [0x%02x]", *p );
  503. X
  504. X      TALLOC( hp, 1, HASH );        /* allocate a cell and add it in */
  505. X
  506. X      if( tab == Defs ) hp->CP_ROOT = dir;
  507. X      hp->ht_name  = _strdup( name );
  508. X      hp->ht_hash  = hash_key;
  509. X      hp->ht_next  = tab[ hv ];
  510. X      tab[ hv ]    = hp;
  511. X
  512. X      DB_PRINT( "name", ("Adding %s", name) );
  513. X   }
  514. X
  515. X   DB_PRINT( "name",("Returning: [%s,%lu]",
  516. X         (hp == NIL(HASH)) ? "":hp->ht_name, hv) );
  517. X   DB_RETURN( hp );
  518. X}
  519. X
  520. X
  521. X
  522. XHASHPTR
  523. XDef_macro( name, value, flags )/*
  524. X=================================
  525. X   This routine is used to define a macro, and it's value.
  526. X   The flags indicates if it is a permanent macro or if it's value
  527. X   can be redefined.  A flags of M_PRECIOUS means it is a precious
  528. X   macro and cannot be further redefined.  If the flags flag also
  529. X   contains the M_MULTI bit it means that the macro can be redefined
  530. X   multiple times and no warning of the redefinitions should be issued.
  531. X   Once a macro's VAR flags are set they are preserved through all future
  532. X   macro definitions.
  533. X   
  534. X   Macro definitions that have one of the variable bits set are treated
  535. X   specially.  In each case the hash table entry var field points at the
  536. X   global variable that can be set by assigning to the macro.
  537. X   
  538. X   bit valued global vars must be computed when the macro value is changed.
  539. X   char valued global vars must have the first char of ht_value copied to
  540. X   them.  string valued global vars have the same value as ht_value and should
  541. X   just have the new value of ht_value copied to them.  */
  542. X
  543. Xchar    *name;            /* macro name to define    */
  544. Xchar    *value;            /* macro value to set    */
  545. Xint     flags;            /* initial ht_flags    */
  546. X{
  547. X   register HASHPTR   hp;
  548. X   register char      *p, *q;
  549. X
  550. X   DB_ENTER( "Def_macro" );
  551. X   DB_PRINT( "mac", ("Defining macro %s = %s, %x", name, value, flags) );
  552. X
  553. X   /* check to see if name is in the table, if so then just overwrite
  554. X      the previous definition.  Otherwise allocate a new node, and
  555. X      stuff it in the hash table, at the front of any linked list */
  556. X
  557. X   if( Readenv ) flags |= M_LITERAL;
  558. X
  559. X   hp = Get_name( name, Macs, TRUE, NIL(CELL) );
  560. X
  561. X   if( (hp->ht_flag & M_PRECIOUS) && !(flags & M_FORCE) ) {
  562. X      Warning( "Macro `%s' cannot be redefined", name );
  563. X      DB_RETURN( hp );
  564. X   }
  565. X
  566. X   if( hp->ht_value != NIL(char) ) FREE( hp->ht_value );
  567. X
  568. X   if( (hp->ht_flag & M_USED) && !((flags | hp->ht_flag) & M_MULTI) )
  569. X      Warning( "Macro `%s' redefined after use", name );
  570. X
  571. X   if( (value != NIL(char)) && (*value) ) {
  572. X      /* strip out any \<nl> combinations where \ is the current CONTINUATION
  573. X       * char */
  574. X
  575. X      for( p = value; (p = strchr(p, CONTINUATION_CHAR)) != NIL(char); )
  576. X         if( p[1] == '\n' )
  577. X        strcpy( p, p+2 );
  578. X     else
  579. X        p++;
  580. X
  581. X      if( !(flags & M_LITERAL) ) {
  582. X     p = _strdup( _strspn( value, " \t" ) ); /* strip white space before */
  583. X                         /* ... and after value         */
  584. X     if( *p ) {
  585. X        for(q=p+strlen(p)-1; ((*q == ' ')||(*q == '\t')); q--);
  586. X        *++q = '\0';
  587. X     }
  588. X     flags &= ~M_LITERAL;
  589. X      }
  590. X      else
  591. X     p = _strdup( value );               /* take string literally   */
  592. X      
  593. X      if( !*p )    {                /* check if result is ""   */
  594. X         FREE( p );
  595. X         p = NIL(char);
  596. X     flags |= M_EXPANDED;
  597. X      }
  598. X      else if( *_strpbrk( p, "${}" ) == '\0' )
  599. X     flags |= M_EXPANDED;
  600. X
  601. X      hp->ht_value = p;
  602. X   }
  603. X   else
  604. X      hp->ht_value = NIL(char);
  605. X
  606. X   /* Assign the hash table flag less the M_MULTI flag, it is used only
  607. X    * to silence the warning.  But carry it over if it was previously
  608. X    * defined in ht_flag, as this is a permanent M_MULTI variable. */
  609. X
  610. X   hp->ht_flag = (flags & ~(M_MULTI|M_FORCE)) |
  611. X         (hp->ht_flag & (M_VAR_MASK | M_MULTI));
  612. X   
  613. X   /* Check for macro variables and make the necessary adjustment in the
  614. X    * corresponding global variables */
  615. X    
  616. X   if( hp->ht_flag & M_VAR_MASK )
  617. X      if( !(flags & M_EXPANDED) )
  618. X     Error( "Macro variables must be assigned with :=" );
  619. X      else switch( hp->ht_flag & M_VAR_MASK )    /* only one var type per var */
  620. X      {
  621. X     case M_VAR_STRING:
  622. X        *hp->MV_SVAR = hp->ht_value;
  623. X        break;
  624. X
  625. X     case M_VAR_CHAR:
  626. X        *hp->MV_CVAR = (hp->ht_value == NIL(char)) ? '\0':*hp->ht_value;
  627. X        break;
  628. X  
  629. X     case M_VAR_INT: {
  630. X        int tvalue;
  631. X        if( hp->MV_IVAR == NIL(int) ) break;    /* first time */
  632. X
  633. X        tvalue = atoi(hp->ht_value);
  634. X        if( hp->MV_IVAR == &Buffer_size ) {
  635. X           /* If Buffer_size is modified then make sure you change the
  636. X            * size of the real buffer as well. */
  637. X           tvalue = (tvalue < (BUFSIZ-2)) ? BUFSIZ : tvalue+2;
  638. X           if( Buffer_size == tvalue ) break;
  639. X           if( Buffer ) FREE(Buffer);
  640. X           if((Buffer=MALLOC(tvalue, char)) == NIL(char)) No_ram();
  641. X           *Buffer = '\0';
  642. X        }
  643. X        *hp->MV_IVAR = tvalue;
  644. X
  645. X        if( hp->MV_IVAR == &Max_proc || hp->MV_IVAR == &Max_proclmt ) {
  646. X           if( tvalue < 1 )
  647. X          Fatal( "Process limit value must be > 1" );
  648. X
  649. X           if( Max_proc > Max_proclmt )
  650. X          Fatal( "Specified # of processes exceeds limit of [%d]",
  651. X             Max_proclmt );
  652. X        }
  653. X     } break;
  654. X     case M_VAR_BIT:
  655. X        /* Bit variables are set to 1 if ht_value is not NULL and 0
  656. X         * otherwise */
  657. X         
  658. X        if( hp->ht_value == NIL(char) )
  659. X           *hp->MV_BVAR &= ~hp->MV_MASK;
  660. X        else
  661. X           *hp->MV_BVAR |= hp->MV_MASK;
  662. X        break;
  663. X      }
  664. X   
  665. X   DB_RETURN( hp );
  666. X}
  667. X
  668. X
  669. X
  670. XCELLPTR
  671. XDef_cell( name, dir )/*
  672. X=======================
  673. X   Take a string passed in and define it as a cell
  674. X   If the cell exists then return a pointer to it. */
  675. Xchar    *name;
  676. XCELLPTR dir;
  677. X{
  678. X   register HASHPTR  hp;
  679. X   register CELLPTR  cp;
  680. X   register CELLPTR  lib;
  681. X   char             *member;
  682. X   char             *end;
  683. X
  684. X   DB_ENTER( "Def_cell" );
  685. X
  686. X   /* Check to see if the cell is a member of the form lib(member) or
  687. X    * lib((symbol)) and handle the cases appropriately.
  688. X    * What we do is we look at the target, if it is of the above two
  689. X    * forms we get the lib, and add the member/symbol to the list of
  690. X    * prerequisites for the library.  If this is a symbol name def'n
  691. X    * we additionally add the attribute A_SYMBOL, so that stat can
  692. X    * try to do the right thing.  */
  693. X
  694. X   if( ((member = strchr(name, '('))     != NIL(char)) &&
  695. X       ((end    = strrchr(member,  ')')) != NIL(char)) &&
  696. X       (member > name) && (member[-1] != '$') &&
  697. X       (end > member+1)  && (end[1] == '\0') )
  698. X   {
  699. X      *member++ = *end = '\0';
  700. X
  701. X      if( (*member == '(') && (member[strlen(member)-1] == ')') ) {
  702. X     member[ strlen(member)-1 ] = '\0';
  703. X     cp = Def_cell( member+1, dir );
  704. X     cp->ce_attr |= A_SYMBOL;
  705. X      }
  706. X      else
  707. X     cp = Def_cell( member, dir );
  708. X
  709. X      lib  = Def_cell( name, dir );
  710. X
  711. X      if( lib->CE_HOW == NIL(HOW) ) TALLOC( lib->CE_HOW, 1, HOW );
  712. X
  713. X      Add_prerequisite( lib->CE_HOW, cp, FALSE );
  714. X      lib->ce_attr |= A_LIBRARY | A_COMPOSITE;
  715. X
  716. X      if( !Def_targets ) cp = lib;
  717. X   }
  718. X   else {
  719. X      hp = Get_name( name, Defs, TRUE, dir );/* get the name from hash table */
  720. X
  721. X      if( hp->CP_OWNR == NIL(CELL) )    /* was it previously defined    */
  722. X      {                    /* NO, so define a new cell    */
  723. X     DB_PRINT( "cell", ("Defining cell [%s]", name) );
  724. X
  725. X     TALLOC( cp, 1, CELL );
  726. X     hp->CP_OWNR = cp;
  727. X     cp->ce_name = hp;
  728. X      }
  729. X      else                 /* YES, so return the old cell    */
  730. X      {
  731. X     DB_PRINT( "cell", ("Getting cell [%s]", hp->ht_name) );
  732. X     cp = hp->CP_OWNR;
  733. X      }
  734. X   }
  735. X
  736. X   DB_RETURN( cp );
  737. X}
  738. X
  739. X
  740. X
  741. X
  742. XLINKPTR
  743. XAdd_prerequisite( how, cell, head )/*
  744. X=====================================
  745. X    Add a dependency node to the dag.  It adds it to the prerequisites,
  746. X    if any, of the cell and makes certain they are in linear order.
  747. X    If head == 1, then add to head of the prerequisite list, else
  748. X    add to tail. */
  749. X
  750. XHOWPTR  how;
  751. XCELLPTR cell;
  752. Xint     head;
  753. X{
  754. X   register LINKPTR lp, tlp;
  755. X
  756. X   DB_ENTER( "Add_prerequisite" );
  757. X   DB_PRINT( "cell", ("Defining prerequisite %s", cell->CE_NAME) );
  758. X
  759. X   if( (cell->ce_flag & (F_MAGIC | F_PERCENT)) )
  760. X      Fatal( "Special target [%s] cannot be a prerequisite",
  761. X             cell->CE_NAME );
  762. X
  763. X   if( how->hw_prq == NIL(LINK) ) {    /* it's the first one    */
  764. X      TALLOC( lp, 1, LINK );
  765. X      lp->cl_prq    = cell;
  766. X      how->hw_prq   = lp;
  767. X   }
  768. X   else    {    /* search the list, checking for duplicates    */
  769. X      for( lp = how->hw_prq;
  770. X       (lp->cl_next != NIL(LINK)) && (lp->cl_prq != cell);
  771. X       lp = lp->cl_next );
  772. X
  773. X      /* If the cell is not found and we are at the last cell in the list,
  774. X       * allocate a new cell and place it into the list, insert it at the
  775. X       * head if head == 1, else we add it to the end. */
  776. X
  777. X      if( (lp->cl_prq != cell) ) {
  778. X     TALLOC( tlp, 1, LINK );
  779. X     tlp->cl_prq = cell;
  780. X
  781. X     if( head ) {
  782. X        tlp->cl_next = how->hw_prq;
  783. X        how->hw_prq  = tlp;
  784. X     }
  785. X     else
  786. X        lp->cl_next  = tlp;
  787. X
  788. X     lp = tlp;
  789. X      }
  790. X   }
  791. X
  792. X   DB_RETURN( lp );
  793. X}
  794. X
  795. X
  796. X
  797. Xvoid
  798. XClear_prerequisites( how )/*
  799. X============================
  800. X    Clear out the list of prerequisites, freeing all of the LINK nodes,
  801. X    and setting the list to NULL */
  802. XHOWPTR how;
  803. X{
  804. X   LINKPTR lp, tlp;
  805. X
  806. X   DB_ENTER( "Clear_prerequisites" );
  807. X   DB_PRINT( "cell", ("Nuking prerequisites") );
  808. X
  809. X   if( how == NIL(HOW) ) { DB_VOID_RETURN; }
  810. X
  811. X   for( lp=how->hw_prq; lp != NIL(LINK); lp=tlp ) {
  812. X      tlp=lp->cl_next;
  813. X      FREE( lp );
  814. X   }
  815. X
  816. X   how->hw_prq = NIL(LINK);
  817. X
  818. X   DB_VOID_RETURN;
  819. X}
  820. X
  821. X
  822. X
  823. Xvoid
  824. XAdd_fringe( cp )/*
  825. X================== Take the cell pointed to by cp and put it at the end
  826. X           of the fringe of targets */
  827. XCELLPTR cp;
  828. X{
  829. X   DB_ENTER( "Add_fringe" );
  830. X
  831. X   if( !(cp->ce_attr & A_FRINGE) ) {
  832. X      DB_PRINT( "cell", ("Adding to fringe %s", cp->ce_name->ht_name) );
  833. X
  834. X      if( Fringe_hd == NIL(LINK) ) {
  835. X     TALLOC( Fringe_hd, 1, LINK );
  836. X     Fringe_tl = Fringe_hd;
  837. X      }
  838. X      else if( Fringe_tl != NIL(LINK) ) {
  839. X     TALLOC( Fringe_tl->cl_next, 1, LINK );
  840. X     Fringe_tl = Fringe_tl->cl_next;
  841. X      }
  842. X
  843. X      Fringe_tl->cl_prq = cp;
  844. X      cp->ce_attr |= A_FRINGE;
  845. X   }
  846. X
  847. X   DB_VOID_RETURN;
  848. X}
  849. X
  850. X
  851. X
  852. X
  853. Xvoid
  854. XCheck_circle( lp )/*
  855. X====================
  856. X    Check for circular definitions in the make graph */
  857. XLINKPTR lp;
  858. X{
  859. X   for( ; lp != NIL(LINK); lp = lp->cl_next )
  860. X      if( Test_circle( lp->cl_prq, FALSE ) )
  861. X     Fatal( "Detected circular dependency in graph at [%s]",
  862. X        lp->cl_prq->CE_NAME );
  863. X}
  864. X
  865. X
  866. X
  867. X
  868. Xint
  869. XTest_circle( cp, meta )/*
  870. X=========================
  871. X    Actually run through the graph */
  872. XCELLPTR cp;
  873. Xint     meta;
  874. X{
  875. X   int res = 0;
  876. X   DB_ENTER( "Test_circle" );
  877. X   DB_PRINT( "tc", ("checking [%s]", cp->CE_NAME) );
  878. X
  879. X   if( cp->ce_flag & F_MARK )
  880. X      DB_RETURN( (cp->ce_attr & A_LIBRARY) ? 0 : 1 );
  881. X
  882. X   cp->ce_flag |= F_MARK;
  883. X
  884. X   if( meta ) {
  885. X      register EDGEPTR ep;
  886. X
  887. X      if( cp->CE_EDGES != NIL(EDGE) ) {
  888. X     EDGEPTR es;
  889. X
  890. X     ep = es = cp->CE_EDGES;
  891. X     do {
  892. X        if( ep->ed_prq != NIL(CELL) && ep->ed_prq->ce_flag & F_DFA )
  893. X           res = Test_circle( ep->ed_prq, TRUE );
  894. X        ep = ep->ed_next;
  895. X     }
  896. X     while( ep != es && !res );
  897. X      }
  898. X   }
  899. X   else {
  900. X      register LINKPTR tcp;
  901. X
  902. X      if( cp->CE_HOW != NIL(HOW) )
  903. X     for( tcp = cp->CE_HOW->hw_prq; !res && tcp != NIL(LINK);
  904. X          tcp = tcp->cl_next )
  905. X        if( tcp->cl_prq != cp ) res = Test_circle( tcp->cl_prq, FALSE );
  906. X   }
  907. X
  908. X   cp->ce_flag ^= F_MARK;
  909. X   DB_RETURN( res );
  910. X}
  911. X
  912. X
  913. X
  914. X
  915. XSTRINGPTR
  916. XDef_recipe( rcp, sp, white_too, no_check )/*
  917. X=============================================
  918. X    Take the recipe and add it to the list of recipes
  919. X    pointed to by sp.  sp points to the last element.
  920. X    return a pointer to the new recipe.  If white_too == TRUE add the
  921. X    recipe even if it contains only white space.
  922. X    If no_check is true then don't look for -@ at the start of the
  923. X    recipe line. */
  924. Xchar      *rcp;
  925. XSTRINGPTR sp;
  926. Xint       white_too;
  927. Xint       no_check;
  928. X{
  929. X   register STRINGPTR nsp;
  930. X   register char      *rp;
  931. X   int                flag;
  932. X   int                done;
  933. X
  934. X   DB_ENTER( "Def_recipe" );
  935. X   DB_PRINT( "rul", ("Defining recipe %s", rcp) );
  936. X
  937. X   if( !white_too ) rcp = _strspn( rcp, " \t" );
  938. X   if( (rcp == NIL(char)) || (*rcp == 0 && !white_too) )
  939. X      DB_RETURN( sp );         /* return last recipe when new recipe not added */
  940. X
  941. X   rp = no_check ? rcp : _strspn( rcp, " \t@-" );
  942. X
  943. X   TALLOC( nsp, 1, STRING );
  944. X   nsp->st_string = _strdup( rp );
  945. X
  946. X   if( sp != NIL(STRING) ) sp->st_next = nsp;
  947. X   nsp->st_next = NIL(STRING);
  948. X
  949. X   if( no_check ) DB_RETURN( nsp );
  950. X
  951. X   for( flag = A_DEFAULT, rp = rcp, done = FALSE; !done; )
  952. X      switch( *rp++ )
  953. X      {
  954. X     case '@' : flag |= A_SILENT; break;
  955. X     case '-' : flag |= A_IGNORE; break;
  956. X
  957. X     case ' ' :
  958. X     case '\t': break;
  959. X
  960. X     default: done = TRUE; break;
  961. X      }
  962. X
  963. X   nsp->st_attr |= flag;
  964. X
  965. X   DB_RETURN( nsp );
  966. X}
  967. SHAR_EOF
  968. chmod 0440 dag.c || echo "restore of dag.c fails"
  969. echo mkdir - common
  970. mkdir common
  971. echo "x - extracting common/print.mk (Text)"
  972. sed 's/^X//' << 'SHAR_EOF' > common/print.mk &&
  973. X# Make a listing of either everything so far, or just the stuff that has
  974. X# been updated since the last time a printout was made.
  975. X# The targets are:
  976. X#    print        - to print only updated files.
  977. X#    printall    - to print entire tree.
  978. X#
  979. X# MACROS are:
  980. X#    PRINTER        - printer name on which to put output, output
  981. X#              goes to a file if no printer name is given.
  982. X#    PRINTFLAGS    - flags to pass to the printer.
  983. X#    PRINTEXCLUDE    - substrings in file names not to include in output.
  984. X
  985. XGROUPFLAGS  :=
  986. XSEDLIST = _sed_e_flag_'/{ $(PRINTEXCLUDE) }/d'
  987. XFILIST  = $(TMPDIR)/pr$$$$
  988. XOFILE   = $(TMPDIR)/pr$$$$.out
  989. X
  990. X.IF $(PRINTEXCLUDE)
  991. X   SEDARGS = $(SEDLIST:s/_sed_e_flag_/-e /)
  992. X.END
  993. X
  994. Xprintall : print_remove_ctl print;
  995. Xprint_remove_ctl:;@-$(RM) control/print
  996. X
  997. Xprint:
  998. X@[
  999. X   if [ -f control/print ]; then
  1000. X      find . -type f -newer control/print -print |\
  1001. X      sort -t. +2 +1 -2 |\
  1002. X      sed $(SEDARGS) >$(FILIST);
  1003. X      if [ -s $(FILIST) ]; then
  1004. X     find . -type f -print | sort -t. +2 +1 -2 |\
  1005. X     sed $(SEDARGS) >$(FILIST).full;
  1006. X     cpr -c -T control/title -N -C `cat $(FILIST).full` >$(OFILE);
  1007. X     cpr -c -N `cat $(FILIST)` >> $(OFILE);
  1008. X     $(RM) $(FILIST).full;
  1009. X      else
  1010. X     echo "No modified files since last printing";
  1011. X      fi
  1012. X   else
  1013. X      find . -type f -print | sort -t. +2 +1 -2 |\
  1014. X      sed $(SEDARGS) >$(FILIST);
  1015. X      if [ -s $(FILIST) ]; then
  1016. X     cpr -c -T control/title -N `cat $(FILIST)` >$(OFILE);
  1017. X      fi
  1018. X   fi
  1019. X
  1020. X   if [ -s $(OFILE) ]; then
  1021. X.IF $(PRINTER)
  1022. X      $(PRINT) $(PRINTFLAGS) $(OFILE);
  1023. X      echo "Listing printed on $(PRINTER)";
  1024. X.IF $(PRINTKEEPTMP) == $(NULL)
  1025. X      $(RM) $(OFILE);
  1026. X.END
  1027. X.ELSE
  1028. X      echo "Listing can be temporarily found in $(OFILE)";
  1029. X.END
  1030. X   fi
  1031. X.IF $(PRINTKEEPTMP) == $(NULL)
  1032. X   $(RM) $(FILIST)
  1033. X.END
  1034. X   touch control/print;
  1035. X   exit 0
  1036. X]
  1037. SHAR_EOF
  1038. chmod 0662 common/print.mk || echo "restore of common/print.mk fails"
  1039. echo "x - extracting common/malloc.c (Text)"
  1040. sed 's/^X//' << 'SHAR_EOF' > common/malloc.c &&
  1041. X/* RCS      -- $Header: /u2/dvadura/src/generic/dmake/src/common/RCS/malloc.c,v 1.1 90/07/19 13:31:06 dvadura Exp $
  1042. X-- SYNOPSIS -- debugging version of malloc
  1043. X-- 
  1044. X-- DESCRIPTION
  1045. X--     malloc for debugging -- allocates via sbrk and tracks stuff, does diag
  1046. X--     dump if things appear to be screwed up.  This code is taken from a
  1047. X--    malloc package off the net.  By the time I got it the original authors
  1048. X--    name had disappeared.   This file can be used by anyone for any
  1049. X--    purpose, since it is originally from usenet, hence the missing
  1050. X--    copyright notice.
  1051. X-- 
  1052. X-- AUTHOR
  1053. X--      Dennis Vadura, dvadura@watdragon.uwaterloo.ca
  1054. X--      CS DEPT, University of Waterloo, Waterloo, Ont., Canada
  1055. X--
  1056. X-- LOG
  1057. X--     $Log:    malloc.c,v $
  1058. X * Revision 1.1  90/07/19  13:31:06  dvadura
  1059. X * Initial Revision of Version 3.5
  1060. X * 
  1061. X*/
  1062. X
  1063. X#ifdef DBUG
  1064. X
  1065. X#include <signal.h>
  1066. X#include "extern.h"
  1067. X#include "alloc.h"
  1068. X#include "db.h"
  1069. X
  1070. Xextern char *sbrk();
  1071. Xextern char etext[];
  1072. Xextern char edata[];
  1073. Xextern char end[];
  1074. X
  1075. Xvoid
  1076. XMy_free( ptr, fil, line )/*
  1077. X===========================
  1078. X   A routine that check the freeing of NULL pointers. */
  1079. Xchar *ptr;
  1080. Xchar *fil;
  1081. Xint  line;
  1082. X{
  1083. X#ifdef DB_MALLOC
  1084. X   _malldstr( "free: file:" );
  1085. X   _malldstr( fil );
  1086. X   _malldstr( " line: " );
  1087. X   _dbdumpint( line );
  1088. X   _malldstr( " ::  " );
  1089. X#endif
  1090. X
  1091. X   if( ptr == NIL( char ) )
  1092. X      Fatal( "Freeing NIL pointer" );
  1093. X
  1094. X   free( ptr );
  1095. X}
  1096. X
  1097. X
  1098. Xchar *
  1099. XMy_malloc( n, fil, line )/*
  1100. X===========================
  1101. X   A routine that check alloc */
  1102. Xunsigned int n;
  1103. Xchar *fil;
  1104. Xint  line;
  1105. X{
  1106. X#ifdef DB_MALLOC
  1107. X   _malldstr( "alloc: file:" );
  1108. X   _malldstr( fil );
  1109. X   _malldstr( " line: " );
  1110. X   _dbdumpint( line );
  1111. X   _malldstr( " ::  " );
  1112. X#endif
  1113. X
  1114. X   return( malloc( n ));
  1115. X}
  1116. X
  1117. X
  1118. X
  1119. Xchar *
  1120. XMy_calloc( n, size, fil, line )/*
  1121. X=================================
  1122. X   A routine that check alloc */
  1123. Xunsigned int n;
  1124. Xunsigned int size;
  1125. Xchar *fil;
  1126. Xint  line;
  1127. X{
  1128. X#ifdef DB_MALLOC
  1129. X   _malldstr( "alloc: file:" );
  1130. X   _malldstr( fil );
  1131. X   _malldstr( " line: " );
  1132. X   _dbdumpint( line );
  1133. X   _malldstr( " ::  " );
  1134. X#endif
  1135. X
  1136. X   return( calloc( n, size ));
  1137. X}
  1138. X
  1139. X
  1140. X
  1141. X#ifdef DB_MALLOC
  1142. X
  1143. Xstruct _Dmi {
  1144. X    struct _Dmi *m_next;
  1145. X    struct _Dmi *m_prev;
  1146. X    long m_size;
  1147. X    char m_blk[1];
  1148. X};
  1149. X
  1150. Xstatic struct _Dmi *_fab = (struct _Dmi *) 0;
  1151. Xstatic struct _Dmi *_ffb = (struct _Dmi *) 0;
  1152. Xstatic char *_xbrk = 0;
  1153. Xstatic int _in_malloc = 0;
  1154. Xstatic int _st_malloc = 0;
  1155. Xint _mall_opt = 1;
  1156. X
  1157. X/*
  1158. X * initialize stuff, we want to _malldmp() on a bus/seg error
  1159. X */
  1160. X
  1161. Xstatic _mall_sig(sig) {
  1162. X    if (sig == SIGSEGV)
  1163. X        _malldstr("\nsegmentation violation\n\n");
  1164. X    else if (sig == SIGBUS)
  1165. X        _malldstr("\nbus error\n\n");
  1166. X    else if (sig == SIGSYS)
  1167. X        _malldstr("\ninvalid syscall arg\n\n");
  1168. X    else {
  1169. X        _malldstr("\nsignal ");
  1170. X        _malldptr(sig);
  1171. X        _malldstr("\n\n");
  1172. X    }
  1173. X    _malldmp();
  1174. X    kill(getpid(), sig);
  1175. X}
  1176. X
  1177. Xstatic _mall_init() {
  1178. X    if (_st_malloc)
  1179. X        return;
  1180. X    signal(SIGSEGV, _mall_sig);
  1181. X    signal(SIGBUS, _mall_sig);
  1182. X    _st_malloc = 1;
  1183. X}
  1184. X
  1185. X/*
  1186. X * figure out which allocation block this pointer came from
  1187. X * return NULL if none
  1188. X */
  1189. X
  1190. Xstatic struct _Dmi *_mallgb(s)
  1191. Xchar *s; {
  1192. X    register struct _Dmi *blk;
  1193. X
  1194. X    for (blk = _fab; blk != (struct _Dmi *) 0; blk = blk->m_next)
  1195. X        if (blk->m_blk == s)
  1196. X            break;
  1197. X    return blk;
  1198. X}
  1199. X
  1200. X
  1201. X/*
  1202. X * internal: write a pointer in hex without using stdio
  1203. X */
  1204. X
  1205. Xstatic _malldptr(x)
  1206. Xregister long x; {
  1207. X    char buf[20];
  1208. X    static char hex[] = "0123456789abcdef";
  1209. X    register long dx;
  1210. X    register char *p;
  1211. X
  1212. X    if (x == 0)
  1213. X        return _malldstr("0x0(0)");
  1214. X    _malldstr("0x");
  1215. X    p = buf;
  1216. X    dx = x;
  1217. X    while (x > 0)
  1218. X        *p++ = hex[x % 16], x = x / 16;
  1219. X    while (p != buf)
  1220. X        write(2, --p, 1);
  1221. X    _malldstr("(");
  1222. X    p = buf;
  1223. X    x = dx;
  1224. X    while (x > 0)
  1225. X        *p++ = hex[x % 10], x /= 10;
  1226. X    while (p != buf)
  1227. X        write(2, --p, 1);
  1228. X    _malldstr(")");
  1229. X}
  1230. X
  1231. X/*
  1232. X * internal: dump a string
  1233. X */
  1234. X
  1235. Xstatic _malldstr(s)
  1236. Xregister char *s; {
  1237. X    register int len;
  1238. X
  1239. X    for (len = 0; s[len] != '\0'; len++)
  1240. X        ;
  1241. X    write(2, s, len);
  1242. X}
  1243. X
  1244. X
  1245. Xstatic _dbdumpint(x)
  1246. Xregister int x; {
  1247. X    char buf[20];
  1248. X    static char hex[] = "0123456789abcdef";
  1249. X    register long dx;
  1250. X    register char *p;
  1251. X
  1252. X    if (x == 0) return _malldstr("0");
  1253. X    p = buf;
  1254. X    while (x > 0)
  1255. X        *p++ = hex[x % 10], x /= 10;
  1256. X    while (p != buf)
  1257. X        write(2, --p, 1);
  1258. X}
  1259. X
  1260. X
  1261. X/*
  1262. X * dump arena; can be called externally, and is non-destructive
  1263. X */
  1264. X
  1265. X_malldmp() {
  1266. X    register struct _Dmi *blk;
  1267. X    int oldf;
  1268. X
  1269. X    oldf = _in_malloc;
  1270. X    _in_malloc = 0;
  1271. X    _malldstr("brk = ");
  1272. X    _malldptr(sbrk(0));
  1273. X    _malldstr("  xbrk = ");
  1274. X    _malldptr(_xbrk);
  1275. X    _malldstr("\n_fab = ");
  1276. X    _malldptr(_fab);
  1277. X    _malldstr("  _ffb = ");
  1278. X    _malldptr(_ffb);
  1279. X    _malldstr("  blksiz = ");
  1280. X    _malldptr(sizeof (struct _Dmi));
  1281. X    _malldstr("\netext = ");
  1282. X    _malldptr(etext);
  1283. X    _malldstr("  edata = ");
  1284. X    _malldptr(edata);
  1285. X    _malldstr("  end = ");
  1286. X    _malldptr(end);
  1287. X    _malldstr("\n\nallocated blocks\n\n");
  1288. X    if (_fab == (struct _Dmi *) 0)
  1289. X        _malldstr("(none)\n");
  1290. X    else {
  1291. X        for (blk = _fab; blk != (struct _Dmi *) 0 && (char *) blk >= _xbrk && (char *) blk < sbrk(0); blk = blk->m_next) {
  1292. X            _malldstr("(");
  1293. X            _malldptr(blk);
  1294. X            _malldstr(")  ");
  1295. X            _malldptr(blk->m_prev);
  1296. X            _malldstr("<  ");
  1297. X            _malldptr(blk->m_size);
  1298. X            _malldstr("  >");
  1299. X            _malldptr(blk->m_next);
  1300. X            _malldstr("\n");
  1301. X        }
  1302. X        if (blk != (struct _Dmi *) 0)
  1303. X            _malldstr("(subsequent block pointers corrupted)\n");
  1304. X    }
  1305. X    _malldstr("\nfree blocks\n\n");
  1306. X    if (_ffb == (struct _Dmi *) 0)
  1307. X        _malldstr("(none)\n");
  1308. X    else {
  1309. X        for (blk = _ffb; blk != (struct _Dmi *) 0 && (char *) blk >= _xbrk && (char *) blk < sbrk(0); blk = blk->m_next) {
  1310. X            _malldstr("(");
  1311. X            _malldptr(blk);
  1312. X            _malldstr(")  ");
  1313. X            _malldptr(blk->m_prev);
  1314. X            _malldstr("<  ");
  1315. X            _malldptr(blk->m_size);
  1316. X            _malldstr("  >");
  1317. X            _malldptr(blk->m_next);
  1318. X            _malldstr("\n");
  1319. X        }
  1320. X        if (blk != (struct _Dmi *) 0)
  1321. X            _malldstr("(subsequent block pointers corrupted)\n");
  1322. X    }
  1323. X    _in_malloc = oldf;
  1324. X}
  1325. X
  1326. X/*
  1327. X * internal error routine: print error message (without using stdio) and
  1328. X * drop core
  1329. X */
  1330. X
  1331. Xstatic _mallerr(fn, s, ptr)
  1332. Xchar *fn, *s;
  1333. Xlong ptr; {
  1334. X    _malldstr(fn);
  1335. X    _malldstr(": ");
  1336. X    _malldstr(s);
  1337. X    _malldptr(ptr);
  1338. X    _malldstr("\n");
  1339. X    _malldmp();
  1340. X    signal(SIGQUIT, SIG_DFL);
  1341. X    kill(getpid(), SIGQUIT);
  1342. X}
  1343. X    
  1344. Xchar *malloc(n )
  1345. Xregister unsigned n;
  1346. X{
  1347. X    register struct _Dmi *blk;
  1348. X
  1349. X    _in_malloc = 1;
  1350. X    _mall_init();
  1351. X    if (_mall_opt)
  1352. X    {
  1353. X         _malldstr("malloc: size: " );
  1354. X         _malldptr(n);
  1355. X         _malldstr("\n");
  1356. X    }
  1357. X    _mallchk("malloc");
  1358. X    if (n == 0) {
  1359. X        _malldstr("malloc(0) is illegal!\n");
  1360. X        _mall_sig(SIGSYS);
  1361. X    }
  1362. X    for (blk = _ffb; blk != (struct _Dmi *) 0; blk = blk->m_next)
  1363. X        if (blk->m_size >= n) {
  1364. X            if (blk->m_next != (struct _Dmi *) 0)
  1365. X                blk->m_next->m_prev = blk->m_prev;
  1366. X            if (blk->m_prev != (struct _Dmi *) 0)
  1367. X                blk->m_prev->m_next = blk->m_next;
  1368. X            if (blk == _ffb)
  1369. X                _ffb = blk->m_next;
  1370. X            blk->m_next = _fab;
  1371. X            blk->m_prev = (struct _Dmi *) 0;
  1372. X            if (_fab != (struct _Dmi *) 0)
  1373. X                _fab->m_prev = blk;
  1374. X            _fab = blk;
  1375. X            _in_malloc = 0;
  1376. X            return blk->m_blk;
  1377. X        }
  1378. X    if ((blk = (struct _Dmi *) sbrk(sizeof (struct _Dmi) + n - 1)) == (struct _Dmi *) -1) {
  1379. X        _in_malloc = 0;
  1380. X        return (char *) 0;    /* no space */
  1381. X    }
  1382. X    if (_xbrk == (char *) 0)
  1383. X        _xbrk = (char *) blk;
  1384. X    blk->m_next = _fab;
  1385. X    blk->m_prev = (struct _Dmi *) 0;
  1386. X    if (_fab != (struct _Dmi *) 0)
  1387. X        _fab->m_prev = blk;
  1388. X    _fab = blk;
  1389. X    blk->m_size = n;
  1390. X    _in_malloc = 0;
  1391. X    return blk->m_blk;
  1392. X}
  1393. X
  1394. X/* The free-block list is sorted in size order */
  1395. X
  1396. Xfree(s)
  1397. Xregister char *s;
  1398. X{
  1399. X    register struct _Dmi *blk, *fblk;
  1400. X    int didit;
  1401. X
  1402. X    _in_malloc = 1;
  1403. X    _mall_init();
  1404. X    if (_mall_opt)
  1405. X    {
  1406. X         _malldstr("free: ptr: ");
  1407. X         _malldptr(s);
  1408. X         _malldstr("\n");
  1409. X    }
  1410. X    _mallchk("free");
  1411. X    if (s == (char *) 0) {
  1412. X        _malldstr("free((char *) 0) is illegal!\n");
  1413. X        _mall_sig(SIGSYS);
  1414. X    }
  1415. X    if ((blk = _mallgb(s)) == (struct _Dmi *) 0)
  1416. X        _mallerr("non-allocated pointer passed to free(): ", s);
  1417. X    if (blk->m_prev != (struct _Dmi *) 0)
  1418. X        blk->m_prev->m_next = blk->m_next;
  1419. X    if (blk->m_next != (struct _Dmi *) 0)
  1420. X        blk->m_next->m_prev = blk->m_prev;
  1421. X    if (blk == _fab)
  1422. X        _fab = blk->m_next;
  1423. X    if (_ffb == (struct _Dmi *) 0) {
  1424. X        _ffb = blk;
  1425. X        blk->m_next = (struct _Dmi *) 0;
  1426. X        blk->m_prev = (struct _Dmi *) 0;
  1427. X        goto crunch;
  1428. X    }
  1429. X    for (fblk = _ffb; fblk->m_next != (struct _Dmi *) 0; fblk = fblk->m_next)
  1430. X        if (fblk->m_next->m_size >= blk->m_size)
  1431. X            break;
  1432. X    blk->m_next = fblk->m_next;
  1433. X    if (fblk->m_next != (struct _Dmi *) 0)
  1434. X        fblk->m_next->m_prev = blk;
  1435. X    blk->m_prev = fblk;
  1436. X    fblk->m_next = blk;
  1437. X
  1438. X/*
  1439. X * crunch the free list by dropping consecutive end-of-brk until we hit xbrk
  1440. X * or a "hole" (i.e. allocated block).  coalescing is possible but not supp-
  1441. X * orted in malloc, so we don't bother here.
  1442. X */
  1443. X
  1444. Xcrunch:
  1445. X    didit = 1;
  1446. X    while (_ffb != (struct _Dmi *) 0 && didit) {
  1447. X        didit = 0;
  1448. X        for (fblk = _ffb; fblk != (struct _Dmi *) 0; fblk = fblk->m_next)
  1449. X            if ((char *) fblk + sizeof *fblk + fblk->m_size - 1 == sbrk(0)) {
  1450. X                didit = 1;
  1451. X                if (fblk->m_next != (struct _Dmi *) 0)
  1452. X                    fblk->m_next->m_prev = fblk->m_prev;
  1453. X                if (fblk->m_prev != (struct _Dmi *) 0)
  1454. X                    fblk->m_prev->m_next = fblk->m_next;
  1455. X                if (fblk == _ffb)
  1456. X                    _ffb = fblk->m_next;
  1457. X                sbrk(- fblk->m_size);
  1458. X                break;
  1459. X            }
  1460. X    }
  1461. X    _in_malloc = 0;
  1462. X}
  1463. X
  1464. Xchar *realloc(s, n)
  1465. Xregister char *s;
  1466. Xregister unsigned n; {
  1467. X    register char *s1, *d, *d1;
  1468. X    register struct _Dmi *blk;
  1469. X
  1470. X    if (_mall_opt)
  1471. X        _malldstr("called realloc("), _malldptr(s), _malldstr(", "), _malldptr(n), _malldstr(")\n");
  1472. X    _mallchk("realloc");
  1473. X    if (s == (char *) 0) {
  1474. X        _malldstr("realloc((char *) 0, size) is illegal!\n");
  1475. X        _mall_sig(SIGSYS);
  1476. X    }
  1477. X    if (n == 0) {
  1478. X        _malldstr("realloc(ptr, 0) is illegal!\n");
  1479. X        _mall_sig(SIGSYS);
  1480. X    }
  1481. X    if ((blk = _mallgb(s)) == (struct _Dmi *) 0)
  1482. X        _mallerr("non-allocated pointer passed to realloc(): ", s);
  1483. X    if ((s1 = malloc(n)) == (char *) 0)
  1484. X        return (char *) 0;
  1485. X    if (blk->m_size < n)
  1486. X        n = blk->m_size;
  1487. X    d1 = s1;
  1488. X    d = s;
  1489. X    while (n-- != 0)
  1490. X        *d1++ = *d++;
  1491. X    free(s);
  1492. X    return s1;
  1493. X}
  1494. X
  1495. X/*
  1496. X * _mallchk() is global, so external routines can do discreet checks on the
  1497. X * arena.  If the arena is detectibly corrupted, it will abort().
  1498. X */
  1499. X
  1500. X_mallchk(fn)
  1501. Xchar *fn; {
  1502. X    register struct _Dmi *blk, *cblk;
  1503. X    register char *send;
  1504. X    register int cnt;
  1505. X
  1506. X    send = sbrk(0);
  1507. X    cblk = (struct _Dmi *) 0;
  1508. X    for (blk = _fab; blk != (struct _Dmi *) 0; cblk = blk, blk = blk->m_next) {
  1509. X        if ((char *) blk < _xbrk || (char *) blk >= send)
  1510. X            _mallerr(fn, "allocated block list corrupted: blkptr = ", blk);
  1511. X        if (blk->m_prev != cblk)
  1512. X            _mallerr(fn, "allocated block list corrupted: back pointer incorrect blk ", blk);
  1513. X        if (blk->m_size < 0)
  1514. X            _mallerr(fn, "allocated block list corrupted: blk->m_size = ", blk->m_size);
  1515. X    }
  1516. X    cblk = (struct _Dmi *) 0;
  1517. X    for (blk = _ffb; blk != (struct _Dmi *) 0; cblk = blk, blk = blk->m_next) {
  1518. X        if ((char *) blk < _xbrk || (char *) blk >= sbrk(0))
  1519. X            _mallerr(fn, "free block list corrupted: blkptr = ", blk);
  1520. X        if (blk->m_prev != cblk)
  1521. X            _mallerr(fn, "free block list corrupted: back pointer incorrect blk ", blk);
  1522. X        if (blk->m_size < 0)
  1523. X            _mallerr(fn, "free block list corrupted: blk->m_size = ", blk->m_size);
  1524. SHAR_EOF
  1525. echo "End of part 18"
  1526. echo "File common/malloc.c is continued in part 19"
  1527. echo "19" > s2_seq_.tmp
  1528. exit 0
  1529.  
  1530.