home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / MISC / GNU / MAK358AS.ZIP / MISC.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-22  |  10.2 KB  |  470 lines

  1. /* Copyright (C) 1988, 1989 Free Software Foundation, Inc.
  2. This file is part of GNU Make.
  3.  
  4. GNU Make is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 1, or (at your option)
  7. any later version.
  8.  
  9. GNU Make is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with GNU Make; see the file COPYING.  If not, write to
  16. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  17.  
  18. /*
  19.  * MS-DOS port (c) 1990 by Thorsten Ohl <ohl@gnu.ai.mit.edu>
  20.  *
  21.  * To this port, the same copying conditions apply as to the
  22.  * original release.
  23.  *
  24.  * IMPORTANT:
  25.  * This file is not identical to the original GNU release!
  26.  * You should have received this code as patch to the official
  27.  * GNU release.
  28.  *
  29.  * MORE IMPORTANT:
  30.  * This port comes with ABSOLUTELY NO WARRANTY.
  31.  *
  32.  * $Header: e:/gnu/make/RCS/misc.c'v 3.58.0.3 90/08/27 01:25:01 tho Exp $
  33.  */
  34.  
  35. #include "make.h"
  36. #include "dep.h"
  37.  
  38.  
  39. /* Compare strings *S1 and *S2.
  40.    Return negative if the first is less, positive if it is greater,
  41.    zero if they are equal.  */
  42.  
  43. int
  44. alpha_compare (s1, s2)
  45.      char **s1, **s2;
  46. {
  47.   if (**s1 != **s2)
  48.     return **s1 - **s2;
  49.   return strcmp (*s1, *s2);
  50. }
  51.  
  52. /* Discard each backslash-newline combination from LINE.
  53.    Backslash-backslash-newline combinations become backslash-newlines.
  54.    This is done by copying the text at LINE into itself.  */
  55.  
  56. void
  57. collapse_continuations (line)
  58.      char *line;
  59. {
  60.   register char *in, *out, *p;
  61.   register int backslash;
  62.   register unsigned int bs_write;
  63.  
  64.   in = index (line, '\n');
  65.   if (in == 0)
  66.     return;
  67.  
  68.   out = in;
  69.   if (out > line)
  70.     while (out[-1] == '\\')
  71.       --out;
  72.  
  73.   while (*in != '\0')
  74.     {
  75.       /* BS_WRITE gets the number of quoted backslashes at
  76.      the end just before IN, and BACKSLASH gets nonzero
  77.      if the next character is quoted.  */
  78.       backslash = 0;
  79.       bs_write = 0;
  80.       for (p = in - 1; p >= line && *p == '\\'; --p)
  81.     {
  82.       if (backslash)
  83.         ++bs_write;
  84.       backslash = !backslash;
  85.  
  86.       /* It should be impossible to go back this far without exiting,
  87.          but if we do, we can't get the right answer.  */
  88.       if (in == out - 1)
  89.         abort ();
  90.     }
  91.  
  92.       /* Output the appropriate number of backslashes.  */
  93.       while (bs_write-- > 0)
  94.     *out++ = '\\';
  95.  
  96.       /* Skip the newline.  */
  97.       ++in;
  98.  
  99.       /* If the newline is quoted, discard following whitespace
  100.      and any preceding whitespace; leave just one space.  */
  101.       if (backslash)
  102.     {
  103.       in = next_token (in);
  104.       while (out > line && (out[-1] == ' ' || out[-1] == '\t'))
  105.         --out;
  106.       *out++ = ' ';
  107.     }
  108.       else
  109.     /* If the newline isn't quoted, put it in the output.  */
  110.     *out++ = '\n';
  111.  
  112.       /* Now copy the following line to the output.
  113.      Stop when we find backslashes followed by a newline.  */
  114.       while (*in != '\0')
  115.     if (*in == '\\')
  116.       {
  117.         p = in + 1;
  118.         while (*p == '\\')
  119.           ++p;
  120.         if (*p == '\n')
  121.           {
  122.         in = p;
  123.         break;
  124.           }
  125.         while (in < p)
  126.           *out++ = *in++;
  127.       }
  128.     else
  129.       *out++ = *in++;
  130.     }
  131.  
  132.   *out = '\0';
  133. }
  134.  
  135.  
  136. /* Remove comments, backslash-newline combinations and whitespace
  137.    following such combinations from LINE.
  138.    This is done by copying the text at LINE into itself.  */
  139.  
  140. void
  141. collapse_line (line)
  142.      char *line;
  143. {
  144.   register char *p, *p2;
  145.   register int backslash;
  146.   register unsigned int bs_write;
  147.  
  148.   /* Collapse backslash-newline continuations.  */
  149.   collapse_continuations (line);
  150.  
  151.   while (1)
  152.     {
  153.       p = index (line, '#');
  154.       if (p == 0)
  155.     break;
  156.  
  157.       backslash = 0;
  158.       bs_write = 0;
  159.       for (p2 = p - 1; p2 > line && *p2 == '\\'; --p2)
  160.     {
  161.       if (backslash)
  162.         ++bs_write;
  163.       backslash = !backslash;
  164.     }
  165.  
  166.       if (!backslash)
  167.     {
  168.       /* Cut off the line at the #.  */
  169.       *p = '\0';
  170.       break;
  171.     }
  172.  
  173.       /* strcpy better copy left to right.  */
  174.       line = p;
  175.       strcpy (p2 + 1 + bs_write, line);
  176.     }
  177. }
  178.  
  179. /* Print N spaces (used by DEBUGPR for target-depth).  */
  180.  
  181. void
  182. print_spaces (n)
  183.      register unsigned int n;
  184. {
  185.   while (n-- > 0)
  186.     putchar (' ');
  187. }
  188.  
  189.  
  190. /* Return a newly-allocated string whose contents
  191.    concatenate those of s1, s2, s3.  */
  192.  
  193. char *
  194. concat (s1, s2, s3)
  195.      register char *s1, *s2, *s3;
  196. {
  197.   register unsigned int len1, len2, len3;
  198.   register char *result;
  199.  
  200.   len1 = *s1 != '\0' ? strlen (s1) : 0;
  201.   len2 = *s2 != '\0' ? strlen (s2) : 0;
  202.   len3 = *s3 != '\0' ? strlen (s3) : 0;
  203.  
  204.   result = (char *) xmalloc (len1 + len2 + len3 + 1);
  205.  
  206.   if (*s1 != '\0')
  207.     bcopy (s1, result, len1);
  208.   if (*s2 != '\0')
  209.     bcopy (s2, result + len1, len2);
  210.   if (*s3 != '\0')
  211.     bcopy (s3, result + len1 + len2, len3);
  212.   *(result + len1 + len2 + len3) = '\0';
  213.  
  214.   return result;
  215. }
  216.  
  217. /* Print an error message and exit.  */
  218.  
  219. /* VARARGS1 */
  220. void
  221. fatal (s1, s2, s3, s4, s5, s6)
  222.      char *s1, *s2, *s3, *s4, *s5, *s6;
  223. {
  224.   if (makelevel == 0)
  225.     fprintf (stderr, "%s: ", program);
  226.   else
  227.     fprintf (stderr, "%s[%u]: ", program, makelevel);
  228.   fprintf (stderr, s1, s2, s3, s4, s5, s6);
  229.   fputs (".  Stop.\n", stderr);
  230.  
  231.   die (1);
  232. }
  233.  
  234. /* Print error message.  `s1' is printf control string, `s2' is arg for it. */
  235.  
  236. /* VARARGS1 */
  237.  
  238. void
  239. error (s1, s2, s3, s4, s5, s6)
  240.      char *s1, *s2, *s3, *s4, *s5, *s6;
  241. {
  242.   if (makelevel == 0)
  243.     fprintf (stderr, "%s: ", program);
  244.   else
  245.     fprintf (stderr, "%s[%u]: ", program, makelevel);
  246.   fprintf (stderr, s1, s2, s3, s4, s5);
  247.   putc ('\n', stderr);
  248.   fflush (stderr);
  249. }
  250.  
  251. /* Print an error message from errno.  */
  252.  
  253. void
  254. perror_with_name (str, name)
  255.      char *str, *name;
  256. {
  257. #ifndef MSDOS
  258.   extern int errno, sys_nerr;
  259.   extern char *sys_errlist[];
  260. #endif /* not MSDOS */
  261.  
  262.   if (errno < sys_nerr)
  263.     error ("%s%s: %s", str, name, sys_errlist[errno]);
  264.   else
  265.     error ("%s%s: Unknown error %d", str, name, errno);
  266. }
  267.  
  268. /* Print an error message from errno and exit.  */
  269.  
  270. void
  271. pfatal_with_name (name)
  272.      char *name;
  273. {
  274. #ifndef MSDOS
  275.   extern int errno, sys_nerr;
  276.   extern char *sys_errlist[];
  277. #endif /* not MSDOS */
  278.  
  279.   if (errno < sys_nerr)
  280.     fatal ("%s: %s", name, sys_errlist[errno]);
  281.   else
  282.     fatal ("%s: Unknown error %d", name, errno);
  283.  
  284.   /* NOTREACHED */
  285. }
  286.  
  287. /* Like malloc but get fatal error if memory is exhausted.  */
  288. #ifdef MSDOS
  289. #include <malloc.h>
  290. #else
  291. extern char *malloc (), *realloc ();
  292. #endif /* ! MSDOS */
  293.  
  294. char *
  295. xmalloc (size)
  296.      unsigned int size;
  297. {
  298.   char *result = malloc (size);
  299.   if (result == 0)
  300.     fatal ("virtual memory exhausted");
  301.   return result;
  302. }
  303.  
  304.  
  305. char *
  306. xrealloc (ptr, size)
  307.      char *ptr;
  308.      unsigned int size;
  309. {
  310.   char *result = realloc (ptr, size);
  311.   if (result == 0)
  312.     fatal ("virtual memory exhausted");
  313.   return result;
  314. }
  315.  
  316. char *
  317. savestring (str, length)
  318.      char *str;
  319.      unsigned int length;
  320. {
  321.   register char *out = (char *) xmalloc (length + 1);
  322.   if (length > 0)
  323.     bcopy (str, out, length);
  324.   out[length] = '\0';
  325.   return out;
  326. }
  327.  
  328. /* Search string BIG (length BLEN) for an occurrence of
  329.    string SMALL (length SLEN).  Return a pointer to the
  330.    beginning of the first occurrence, or return nil if none found.  */
  331.  
  332. char *
  333. sindex (big, blen, small, slen)
  334.      char *big;
  335.      unsigned int blen;
  336.      char *small;
  337.      unsigned int slen;
  338. {
  339.   register unsigned int b;
  340.  
  341.   if (blen < 1)
  342.     blen = strlen (big);
  343.   if (slen < 1)
  344.     slen = strlen (small);
  345.  
  346.   for (b = 0; b < blen; ++b)
  347.     if (big[b] == *small && !strncmp (&big[b + 1], small + 1, slen - 1))
  348.       return (&big[b]);
  349.  
  350.   return 0;
  351. }
  352.  
  353. /* Limited INDEX:
  354.    Search through the string STRING, which ends at LIMIT, for the character C.
  355.    Returns a pointer to the first occurrence, or nil if none is found.
  356.    Like INDEX except that the string searched ends where specified
  357.    instead of at the first null.  */
  358.  
  359. char *
  360. lindex (s, limit, c)
  361.      register char *s, *limit;
  362.      int c;
  363. {
  364.   while (s < limit)
  365.     if (*s++ == c)
  366.       return s - 1;
  367.  
  368.   return 0;
  369. }
  370.  
  371. /* Return the address of the first whitespace or null in the string S.  */
  372.  
  373. char *
  374. end_of_token (s)
  375.      char *s;
  376. {
  377.   register char *p = s;
  378.   register int backslash = 0;
  379.  
  380.   while (*p != '\0' && (backslash || (*p != ' ' && *p != '\t' && *p != '\f')))
  381.     {
  382.       if (*p++ == '\\')
  383.     {
  384.       backslash = !backslash;
  385.       while (*p == '\\')
  386.         {
  387.           backslash = !backslash;
  388.           ++p;
  389.         }
  390.     }
  391.       else
  392.     backslash = 0;
  393.     }
  394.  
  395.   return p;
  396. }
  397.  
  398. /* Return the address of the first nonwhitespace or null in the string S.  */
  399.  
  400. char *
  401. next_token (s)
  402.      char *s;
  403. {
  404.   register char *p = s;
  405.  
  406.   while (*p == ' ' || *p == '\t' || *p == '\f')
  407.     ++p;
  408.   return p;
  409. }
  410.  
  411. /* Find the next token in PTR; return the address of it, and store the
  412.    length of the token into *LENGTHPTR if LENGTHPTR is not nil.  */
  413.  
  414. char *
  415. find_next_token (ptr, lengthptr)
  416.      char **ptr;
  417.      unsigned int *lengthptr;
  418. {
  419.   char *p = next_token (*ptr);
  420.   char *end;
  421.  
  422.   if (*p == '\0')
  423.     return 0;
  424.  
  425.   *ptr = end = end_of_token (p);
  426.   if (lengthptr != 0)
  427.     *lengthptr = end - p;
  428.   return p;
  429. }
  430.  
  431. /* Copy a chain of `struct dep', making a new chain
  432.    with the same contents as the old one.  */
  433.  
  434. struct dep *
  435. copy_dep_chain (d)
  436.      register struct dep *d;
  437. {
  438.   register struct dep *c;
  439.   struct dep *firstnew = 0;
  440.   struct dep *lastnew;
  441.  
  442.   while (d != 0)
  443.     {
  444.       c = (struct dep *) xmalloc (sizeof (struct dep));
  445.       bcopy ((char *) d, (char *) c, sizeof (struct dep));
  446.       if (c->name != 0)
  447.     c->name = savestring (c->name, strlen (c->name));
  448.       c->next = 0;
  449.       if (firstnew == 0)
  450.     firstnew = lastnew = c;
  451.       else
  452.     lastnew = lastnew->next = c;
  453.  
  454.       d = d->next;
  455.     }
  456.  
  457.   return firstnew;
  458. }
  459.  
  460. #ifdef    iAPX286
  461. /* The losing compiler on this machine can't handle this macro.  */
  462.  
  463. char *
  464. dep_name (dep)
  465.      struct dep *dep;
  466. {
  467.   return dep->name == 0 ? dep->file->name : dep->name;
  468. }
  469. #endif
  470.