home *** CD-ROM | disk | FTP | other *** search
/ Amiga MA Magazine 1998 #6 / amigamamagazinepolishissue1998.iso / coders / f2c / src / misc.c < prev    next >
C/C++ Source or Header  |  1999-12-13  |  18KB  |  1,041 lines

  1. /****************************************************************
  2. Copyright 1990, 1992 by AT&T Bell Laboratories and Bellcore.
  3.  
  4. Permission to use, copy, modify, and distribute this software
  5. and its documentation for any purpose and without fee is hereby
  6. granted, provided that the above copyright notice appear in all
  7. copies and that both that the copyright notice and this
  8. permission notice and warranty disclaimer appear in supporting
  9. documentation, and that the names of AT&T Bell Laboratories or
  10. Bellcore or any of their entities not be used in advertising or
  11. publicity pertaining to distribution of the software without
  12. specific, written prior permission.
  13.  
  14. AT&T and Bellcore disclaim all warranties with regard to this
  15. software, including all implied warranties of merchantability
  16. and fitness.  In no event shall AT&T or Bellcore be liable for
  17. any special, indirect or consequential damages or any damages
  18. whatsoever resulting from loss of use, data or profits, whether
  19. in an action of contract, negligence or other tortious action,
  20. arising out of or in connection with the use or performance of
  21. this software.
  22. ****************************************************************/
  23.  
  24. #include "defs.h"
  25.  
  26. int oneof_stg (name, stg, mask)
  27.  Namep name;
  28.  int stg, mask;
  29. {
  30.     if (stg == STGCOMMON && name) {
  31.         if ((mask & M(STGEQUIV)))
  32.             return name->vcommequiv;
  33.         if ((mask & M(STGCOMMON)))
  34.             return !name->vcommequiv;
  35.         }
  36.     return ONEOF(stg, mask);
  37.     }
  38.  
  39.  
  40. /* op_assign -- given a binary opcode, return the associated assignment
  41.    operator */
  42.  
  43. int op_assign (opcode)
  44. int opcode;
  45. {
  46.     int retval = -1;
  47.  
  48.     switch (opcode) {
  49.         case OPPLUS: retval = OPPLUSEQ; break;
  50.     case OPMINUS: retval = OPMINUSEQ; break;
  51.     case OPSTAR: retval = OPSTAREQ; break;
  52.     case OPSLASH: retval = OPSLASHEQ; break;
  53.     case OPMOD: retval = OPMODEQ; break;
  54.     case OPLSHIFT: retval = OPLSHIFTEQ; break;
  55.     case OPRSHIFT: retval = OPRSHIFTEQ; break;
  56.     case OPBITAND: retval = OPBITANDEQ; break;
  57.     case OPBITXOR: retval = OPBITXOREQ; break;
  58.     case OPBITOR: retval = OPBITOREQ; break;
  59.     default:
  60.         erri ("op_assign:  bad opcode '%d'", opcode);
  61.         break;
  62.     } /* switch */
  63.  
  64.     return retval;
  65. } /* op_assign */
  66.  
  67.  
  68.  char *
  69. Alloc(n)    /* error-checking version of malloc */
  70.         /* ckalloc initializes memory to 0; Alloc does not */
  71.  int n;
  72. {
  73.     char errbuf[32];
  74.     register char *rv;
  75.  
  76.     rv = malloc(n);
  77.     if (!rv) {
  78.         sprintf(errbuf, "malloc(%d) failure!", n);
  79.         Fatal(errbuf);
  80.         }
  81.     return rv;
  82.     }
  83.  
  84.  
  85. cpn(n, a, b)
  86. register int n;
  87. register char *a, *b;
  88. {
  89.     while(--n >= 0)
  90.         *b++ = *a++;
  91. }
  92.  
  93.  
  94.  
  95. eqn(n, a, b)
  96. register int n;
  97. register char *a, *b;
  98. {
  99.     while(--n >= 0)
  100.         if(*a++ != *b++)
  101.             return(NO);
  102.     return(YES);
  103. }
  104.  
  105.  
  106.  
  107.  
  108.  
  109.  
  110.  
  111. cmpstr(a, b, la, lb)    /* compare two strings */
  112. register char *a, *b;
  113. ftnint la, lb;
  114. {
  115.     register char *aend, *bend;
  116.     aend = a + la;
  117.     bend = b + lb;
  118.  
  119.  
  120.     if(la <= lb)
  121.     {
  122.         while(a < aend)
  123.             if(*a != *b)
  124.                 return( *a - *b );
  125.             else
  126.             {
  127.                 ++a;
  128.                 ++b;
  129.             }
  130.  
  131.         while(b < bend)
  132.             if(*b != ' ')
  133.                 return(' ' - *b);
  134.             else
  135.                 ++b;
  136.     }
  137.  
  138.     else
  139.     {
  140.         while(b < bend)
  141.             if(*a != *b)
  142.                 return( *a - *b );
  143.             else
  144.             {
  145.                 ++a;
  146.                 ++b;
  147.             }
  148.         while(a < aend)
  149.             if(*a != ' ')
  150.                 return(*a - ' ');
  151.             else
  152.                 ++a;
  153.     }
  154.     return(0);
  155. }
  156.  
  157.  
  158. /* hookup -- Same as LISP NCONC, that is a destructive append of two lists */
  159.  
  160. chainp hookup(x,y)
  161. register chainp x, y;
  162. {
  163.     register chainp p;
  164.  
  165.     if(x == NULL)
  166.         return(y);
  167.  
  168.     for(p = x ; p->nextp ; p = p->nextp)
  169.         ;
  170.     p->nextp = y;
  171.     return(x);
  172. }
  173.  
  174.  
  175.  
  176. struct Listblock *mklist(p)
  177. chainp p;
  178. {
  179.     register struct Listblock *q;
  180.  
  181.     q = ALLOC(Listblock);
  182.     q->tag = TLIST;
  183.     q->listp = p;
  184.     return(q);
  185. }
  186.  
  187.  
  188. chainp mkchain(p,q)
  189. register char * p;
  190. register chainp q;
  191. {
  192.     register chainp r;
  193.  
  194.     if(chains)
  195.     {
  196.         r = chains;
  197.         chains = chains->nextp;
  198.     }
  199.     else
  200.         r = ALLOC(Chain);
  201.  
  202.     r->datap = p;
  203.     r->nextp = q;
  204.     return(r);
  205. }
  206.  
  207.  chainp
  208. revchain(next)
  209.  register chainp next;
  210. {
  211.     register chainp p, prev = 0;
  212.  
  213.     while(p = next) {
  214.         next = p->nextp;
  215.         p->nextp = prev;
  216.         prev = p;
  217.         }
  218.     return prev;
  219.     }
  220.  
  221.  
  222. /* addunder -- turn a cvarname into an external name */
  223. /* The cvarname may already end in _ (to avoid C keywords); */
  224. /* if not, it has room for appending an _. */
  225.  
  226.  char *
  227. addunder(s)
  228.  register char *s;
  229. {
  230.     register int c, i;
  231.     char *s0 = s;
  232.  
  233.     i = 0;
  234.     while(c = *s++)
  235.         if (c == '_')
  236.             i++;
  237.         else
  238.             i = 0;
  239.     if (!i) {
  240.         *s-- = 0;
  241.         *s = '_';
  242.         }
  243.     return( s0 );
  244.     }
  245.  
  246.  
  247. /* copyn -- return a new copy of the input Fortran-string */
  248.  
  249. char *copyn(n, s)
  250. register int n;
  251. register char *s;
  252. {
  253.     register char *p, *q;
  254.  
  255.     p = q = (char *) Alloc(n);
  256.     while(--n >= 0)
  257.         *q++ = *s++;
  258.     return(p);
  259. }
  260.  
  261.  
  262.  
  263. /* copys -- return a new copy of the input C-string */
  264.  
  265. char *copys(s)
  266. char *s;
  267. {
  268.     return( copyn( strlen(s)+1 , s) );
  269. }
  270.  
  271.  
  272.  
  273. /* convci -- Convert Fortran-string to integer; assumes that input is a
  274.    legal number, with no trailing blanks */
  275.  
  276. ftnint convci(n, s)
  277. register int n;
  278. register char *s;
  279. {
  280.     ftnint sum;
  281.     sum = 0;
  282.     while(n-- > 0)
  283.         sum = 10*sum + (*s++ - '0');
  284.     return(sum);
  285. }
  286.  
  287. /* convic - Convert Integer constant to string */
  288.  
  289. char *convic(n)
  290. ftnint n;
  291. {
  292.     static char s[20];
  293.     register char *t;
  294.  
  295.     s[19] = '\0';
  296.     t = s+19;
  297.  
  298.     do    {
  299.         *--t = '0' + n%10;
  300.         n /= 10;
  301.     } while(n > 0);
  302.  
  303.     return(t);
  304. }
  305.  
  306.  
  307.  
  308. /* mkname -- add a new identifier to the environment, including the closed
  309.    hash table. */
  310.  
  311. Namep mkname(s)
  312. register char *s;
  313. {
  314.     struct Hashentry *hp;
  315.     register Namep q;
  316.     register int c, hash, i;
  317.     register char *t;
  318.     char *s0;
  319.     char errbuf[64];
  320.  
  321.     hash = i = 0;
  322.     s0 = s;
  323.     while(c = *s++) {
  324.         hash += c;
  325.         if (c == '_')
  326.             i = 1;
  327.         }
  328.     if (!i && in_vector(s0) >= 0)
  329.         i = 1;
  330.     hash %= maxhash;
  331.  
  332. /* Add the name to the closed hash table */
  333.  
  334.     hp = hashtab + hash;
  335.  
  336.     while(q = hp->varp)
  337.         if( hash == hp->hashval && !strcmp(s0,q->fvarname) )
  338.             return(q);
  339.         else if(++hp >= lasthash)
  340.             hp = hashtab;
  341.  
  342.     if(++nintnames >= maxhash-1)
  343.         many("names", 'n', maxhash);    /* Fatal error */
  344.     hp->varp = q = ALLOC(Nameblock);
  345.     hp->hashval = hash;
  346.     q->tag = TNAME;    /* TNAME means the tag type is NAME */
  347.     c = s - s0;
  348.     if (c > 7 && noextflag) {
  349.         sprintf(errbuf, "\"%.35s%s\" over 6 characters long", s0,
  350.             c > 36 ? "..." : "");
  351.         errext(errbuf);
  352.         }
  353.     q->fvarname = strcpy(mem(c,0), s0);
  354.     t = q->cvarname = mem(c + i + 1, 0);
  355.     s = s0;
  356.     /* add __ to the end of any name containing _ and to any C keyword */
  357.     while(*t = *s++)
  358.         t++;
  359.     if (i) {
  360.         t[0] = t[1] = '_';
  361.         t[2] = 0;
  362.         }
  363.     return(q);
  364. }
  365.  
  366.  
  367. struct Labelblock *mklabel(l)
  368. ftnint l;
  369. {
  370.     register struct Labelblock *lp;
  371.  
  372.     if(l <= 0)
  373.         return(NULL);
  374.  
  375.     for(lp = labeltab ; lp < highlabtab ; ++lp)
  376.         if(lp->stateno == l)
  377.             return(lp);
  378.  
  379.     if(++highlabtab > labtabend)
  380.         many("statement labels", 's', maxstno);
  381.  
  382.     lp->stateno = l;
  383.     lp->labelno = newlabel();
  384.     lp->blklevel = 0;
  385.     lp->labused = NO;
  386.     lp->fmtlabused = NO;
  387.     lp->labdefined = NO;
  388.     lp->labinacc = NO;
  389.     lp->labtype = LABUNKNOWN;
  390.     lp->fmtstring = 0;
  391.     return(lp);
  392. }
  393.  
  394.  
  395. newlabel()
  396. {
  397.     return( ++lastlabno );
  398. }
  399.  
  400.  
  401. /* this label appears in a branch context */
  402.  
  403. struct Labelblock *execlab(stateno)
  404. ftnint stateno;
  405. {
  406.     register struct Labelblock *lp;
  407.  
  408.     if(lp = mklabel(stateno))
  409.     {
  410.         if(lp->labinacc)
  411.             warn1("illegal branch to inner block, statement label %s",
  412.                 convic(stateno) );
  413.         else if(lp->labdefined == NO)
  414.             lp->blklevel = blklevel;
  415.         if(lp->labtype == LABFORMAT)
  416.             err("may not branch to a format");
  417.         else
  418.             lp->labtype = LABEXEC;
  419.     }
  420.     else
  421.         execerr("illegal label %s", convic(stateno));
  422.  
  423.     return(lp);
  424. }
  425.  
  426.  
  427. /* find or put a name in the external symbol table */
  428.  
  429. Extsym *mkext(f,s)
  430. char *f, *s;
  431. {
  432.     Extsym *p;
  433.  
  434.     for(p = extsymtab ; p<nextext ; ++p)
  435.         if(!strcmp(s,p->cextname))
  436.             return( p );
  437.  
  438.     if(nextext >= lastext)
  439.         many("external symbols", 'x', maxext);
  440.  
  441.     nextext->fextname = strcpy(gmem(strlen(f)+1,0), f);
  442.     nextext->cextname = f == s
  443.                 ? nextext->fextname
  444.                 : strcpy(gmem(strlen(s)+1,0), s);
  445.     nextext->extstg = STGUNKNOWN;
  446.     nextext->extp = 0;
  447.     nextext->allextp = 0;
  448.     nextext->extleng = 0;
  449.     nextext->maxleng = 0;
  450.     nextext->extinit = 0;
  451.     nextext->curno = nextext->maxno = 0;
  452.     return( nextext++ );
  453. }
  454.  
  455.  
  456. Addrp builtin(t, s, dbi)
  457. int t, dbi;
  458. char *s;
  459. {
  460.     register Extsym *p;
  461.     register Addrp q;
  462.     extern chainp used_builtins;
  463.  
  464.     p = mkext(s,s);
  465.     if(p->extstg == STGUNKNOWN)
  466.         p->extstg = STGEXT;
  467.     else if(p->extstg != STGEXT)
  468.     {
  469.         errstr("improper use of builtin %s", s);
  470.         return(0);
  471.     }
  472.  
  473.     q = ALLOC(Addrblock);
  474.     q->tag = TADDR;
  475.     q->vtype = t;
  476.     q->vclass = CLPROC;
  477.     q->vstg = STGEXT;
  478.     q->memno = p - extsymtab;
  479.     q->dbl_builtin = dbi;
  480.  
  481. /* A NULL pointer here tells you to use   memno   to check the external
  482.    symbol table */
  483.  
  484.     q -> uname_tag = UNAM_EXTERN;
  485.  
  486. /* Add to the list of used builtins */
  487.  
  488.     if (dbi >= 0)
  489.         add_extern_to_list (q, &used_builtins);
  490.     return(q);
  491. }
  492.  
  493.  
  494.  
  495. add_extern_to_list (addr, list_store)
  496. Addrp addr;
  497. chainp *list_store;
  498. {
  499.     chainp last = CHNULL;
  500.     chainp list;
  501.     int memno;
  502.  
  503.     if (list_store == (chainp *) NULL || addr == (Addrp) NULL)
  504.     return;
  505.  
  506.     list = *list_store;
  507.     memno = addr -> memno;
  508.  
  509.     for (;list; last = list, list = list -> nextp) {
  510.     Addrp this = (Addrp) (list -> datap);
  511.  
  512.     if (this -> tag == TADDR && this -> uname_tag == UNAM_EXTERN &&
  513.         this -> memno == memno)
  514.         return;
  515.     } /* for */
  516.  
  517.     if (*list_store == CHNULL)
  518.     *list_store = mkchain((char *)cpexpr((expptr)addr), CHNULL);
  519.     else
  520.     last->nextp = mkchain((char *)cpexpr((expptr)addr), CHNULL);
  521.  
  522. } /* add_extern_to_list */
  523.  
  524.  
  525. frchain(p)
  526. register chainp *p;
  527. {
  528.     register chainp q;
  529.  
  530.     if(p==0 || *p==0)
  531.         return;
  532.  
  533.     for(q = *p; q->nextp ; q = q->nextp)
  534.         ;
  535.     q->nextp = chains;
  536.     chains = *p;
  537.     *p = 0;
  538. }
  539.  
  540.  void
  541. frexchain(p)
  542.  register chainp *p;
  543. {
  544.     register chainp q, r;
  545.  
  546.     if (q = *p) {
  547.         for(;;q = r) {
  548.             frexpr((expptr)q->datap);
  549.             if (!(r = q->nextp))
  550.                 break;
  551.             }
  552.         q->nextp = chains;
  553.         chains = *p;
  554.         *p = 0;
  555.         }
  556.     }
  557.  
  558.  
  559. tagptr cpblock(n,p)
  560. register int n;
  561. register char * p;
  562. {
  563.     register ptr q;
  564.  
  565.     memcpy((char *)(q = ckalloc(n)), (char *)p, n);
  566.     return( (tagptr) q);
  567. }
  568.  
  569.  
  570.  
  571. ftnint lmax(a, b)
  572. ftnint a, b;
  573. {
  574.     return( a>b ? a : b);
  575. }
  576.  
  577. ftnint lmin(a, b)
  578. ftnint a, b;
  579. {
  580.     return(a < b ? a : b);
  581. }
  582.  
  583.  
  584.  
  585.  
  586. maxtype(t1, t2)
  587. int t1, t2;
  588. {
  589.     int t;
  590.  
  591.     t = t1 >= t2 ? t1 : t2;
  592.     if(t==TYCOMPLEX && (t1==TYDREAL || t2==TYDREAL) )
  593.         t = TYDCOMPLEX;
  594.     return(t);
  595. }
  596.  
  597.  
  598.  
  599. /* return log base 2 of n if n a power of 2; otherwise -1 */
  600. log_2(n)
  601. ftnint n;
  602. {
  603.     int k;
  604.  
  605.     /* trick based on binary representation */
  606.  
  607.     if(n<=0 || (n & (n-1))!=0)
  608.         return(-1);
  609.  
  610.     for(k = 0 ;  n >>= 1  ; ++k)
  611.         ;
  612.     return(k);
  613. }
  614.  
  615.  
  616.  
  617. frrpl()
  618. {
  619.     struct Rplblock *rp;
  620.  
  621.     while(rpllist)
  622.     {
  623.         rp = rpllist->rplnextp;
  624.         free( (charptr) rpllist);
  625.         rpllist = rp;
  626.     }
  627. }
  628.  
  629.  
  630.  
  631. /* Call a Fortran function with an arbitrary list of arguments */
  632.  
  633. int callk_kludge;
  634.  
  635. expptr callk(type, name, args)
  636. int type;
  637. char *name;
  638. chainp args;
  639. {
  640.     register expptr p;
  641.  
  642.     p = mkexpr(OPCALL,
  643.         (expptr)builtin(callk_kludge ? callk_kludge : type, name, 0),
  644.         (expptr)args);
  645.     p->exprblock.vtype = type;
  646.     return(p);
  647. }
  648.  
  649.  
  650.  
  651. expptr call4(type, name, arg1, arg2, arg3, arg4)
  652. int type;
  653. char *name;
  654. expptr arg1, arg2, arg3, arg4;
  655. {
  656.     struct Listblock *args;
  657.     args = mklist( mkchain((char *)arg1,
  658.             mkchain((char *)arg2,
  659.                 mkchain((char *)arg3,
  660.                         mkchain((char *)arg4, CHNULL)) ) ) );
  661.     return( callk(type, name, (chainp)args) );
  662. }
  663.  
  664.  
  665.  
  666.  
  667. expptr call3(type, name, arg1, arg2, arg3)
  668. int type;
  669. char *name;
  670. expptr arg1, arg2, arg3;
  671. {
  672.     struct Listblock *args;
  673.     args = mklist( mkchain((char *)arg1,
  674.             mkchain((char *)arg2,
  675.                 mkchain((char *)arg3, CHNULL) ) ) );
  676.     return( callk(type, name, (chainp)args) );
  677. }
  678.  
  679.  
  680.  
  681.  
  682.  
  683. expptr call2(type, name, arg1, arg2)
  684. int type;
  685. char *name;
  686. expptr arg1, arg2;
  687. {
  688.     struct Listblock *args;
  689.  
  690.     args = mklist( mkchain((char *)arg1, mkchain((char *)arg2, CHNULL) ) );
  691.     return( callk(type,name, (chainp)args) );
  692. }
  693.  
  694.  
  695.  
  696.  
  697. expptr call1(type, name, arg)
  698. int type;
  699. char *name;
  700. expptr arg;
  701. {
  702.     return( callk(type,name, (chainp)mklist(mkchain((char *)arg,CHNULL)) ));
  703. }
  704.  
  705.  
  706. expptr call0(type, name)
  707. int type;
  708. char *name;
  709. {
  710.     return( callk(type, name, CHNULL) );
  711. }
  712.  
  713.  
  714.  
  715. struct Impldoblock *mkiodo(dospec, list)
  716. chainp dospec, list;
  717. {
  718.     register struct Impldoblock *q;
  719.  
  720.     q = ALLOC(Impldoblock);
  721.     q->tag = TIMPLDO;
  722.     q->impdospec = dospec;
  723.     q->datalist = list;
  724.     return(q);
  725. }
  726.  
  727.  
  728.  
  729.  
  730. /* ckalloc -- Allocate 1 memory unit of size   n,   checking for out of
  731.    memory error */
  732.  
  733. ptr ckalloc(n)
  734. register int n;
  735. {
  736.     register ptr p;
  737.     p = (ptr)calloc(1, (unsigned) n);
  738.     if (p || !n)
  739.         return(p);
  740.     fprintf(stderr, "failing to get %d bytes\n",n);
  741.     Fatal("out of memory");
  742.     /* NOT REACHED */ return 0;
  743. }
  744.  
  745.  
  746.  
  747. isaddr(p)
  748. register expptr p;
  749. {
  750.     if(p->tag == TADDR)
  751.         return(YES);
  752.     if(p->tag == TEXPR)
  753.         switch(p->exprblock.opcode)
  754.         {
  755.         case OPCOMMA:
  756.             return( isaddr(p->exprblock.rightp) );
  757.  
  758.         case OPASSIGN:
  759.         case OPASSIGNI:
  760.         case OPPLUSEQ:
  761.         case OPMINUSEQ:
  762.         case OPSLASHEQ:
  763.         case OPMODEQ:
  764.         case OPLSHIFTEQ:
  765.         case OPRSHIFTEQ:
  766.         case OPBITANDEQ:
  767.         case OPBITXOREQ:
  768.         case OPBITOREQ:
  769.             return( isaddr(p->exprblock.leftp) );
  770.         }
  771.     return(NO);
  772. }
  773.  
  774.  
  775.  
  776.  
  777. isstatic(p)
  778. register expptr p;
  779. {
  780.     extern int useauto;
  781.     if(p->headblock.vleng && !ISCONST(p->headblock.vleng))
  782.         return(NO);
  783.  
  784.     switch(p->tag)
  785.     {
  786.     case TCONST:
  787.         return(YES);
  788.  
  789.     case TADDR:
  790.         if(ONEOF(p->addrblock.vstg,MSKSTATIC) &&
  791.             ISCONST(p->addrblock.memoffset) && !useauto)
  792.             return(YES);
  793.  
  794.     default:
  795.         return(NO);
  796.     }
  797. }
  798.  
  799.  
  800.  
  801. /* addressable -- return True iff it is a constant value, or can be
  802.    referenced by constant values */
  803.  
  804. addressable(p)
  805. register expptr p;
  806. {
  807.     switch(p->tag)
  808.     {
  809.     case TCONST:
  810.         return(YES);
  811.  
  812.     case TADDR:
  813.         return( addressable(p->addrblock.memoffset) );
  814.  
  815.     default:
  816.         return(NO);
  817.     }
  818. }
  819.  
  820.  
  821. /* isnegative_const -- returns true if the constant is negative.  Returns
  822.    false for imaginary and nonnumeric constants */
  823.  
  824. int isnegative_const (cp)
  825. struct Constblock *cp;
  826. {
  827.     int retval;
  828.  
  829.     if (cp == NULL)
  830.     return 0;
  831.  
  832.     switch (cp -> vtype) {
  833.         case TYSHORT:
  834.     case TYLONG:
  835.         retval = cp -> Const.ci < 0;
  836.         break;
  837.     case TYREAL:
  838.     case TYDREAL:
  839.         retval = cp->vstg ? *cp->Const.cds[0] == '-'
  840.                   :  cp->Const.cd[0] < 0.0;
  841.         break;
  842.     default:
  843.  
  844.         retval = 0;
  845.         break;
  846.     } /* switch */
  847.  
  848.     return retval;
  849. } /* isnegative_const */
  850.  
  851. negate_const(cp)
  852.  Constp cp;
  853. {
  854.     if (cp == (struct Constblock *) NULL)
  855.     return;
  856.  
  857.     switch (cp -> vtype) {
  858.     case TYSHORT:
  859.     case TYLONG:
  860.         cp -> Const.ci = - cp -> Const.ci;
  861.         break;
  862.     case TYCOMPLEX:
  863.     case TYDCOMPLEX:
  864.         if (cp->vstg)
  865.             switch(*cp->Const.cds[1]) {
  866.             case '-':
  867.                 ++cp->Const.cds[1];
  868.                 break;
  869.             case '0':
  870.                 break;
  871.             default:
  872.                 --cp->Const.cds[1];
  873.             }
  874.         else
  875.                 cp->Const.cd[1] = -cp->Const.cd[1];
  876.         /* no break */
  877.     case TYREAL:
  878.     case TYDREAL:
  879.         if (cp->vstg)
  880.             switch(*cp->Const.cds[0]) {
  881.             case '-':
  882.                 ++cp->Const.cds[0];
  883.                 break;
  884.             case '0':
  885.                 break;
  886.             default:
  887.                 --cp->Const.cds[0];
  888.             }
  889.         else
  890.                 cp->Const.cd[0] = -cp->Const.cd[0];
  891.         break;
  892.     case TYCHAR:
  893.     case TYLOGICAL:
  894.         erri ("negate_const:  can't negate type '%d'", cp -> vtype);
  895.         break;
  896.     default:
  897.         erri ("negate_const:  bad type '%d'",
  898.             cp -> vtype);
  899.         break;
  900.     } /* switch */
  901. } /* negate_const */
  902.  
  903. ffilecopy (infp, outfp)
  904. FILE *infp, *outfp;
  905. {
  906.     while (!feof (infp)) {
  907.     register c = getc (infp);
  908.     if (!feof (infp))
  909.     putc (c, outfp);
  910.     } /* while */
  911. } /* ffilecopy */
  912.  
  913.  
  914. #define NOT_IN_VECTOR -1
  915.  
  916. /* in_vector -- verifies whether   str   is in c_keywords.
  917.    If so, the index is returned else   NOT_IN_VECTOR   is returned.
  918.    c_keywords must be in alphabetical order (as defined by strcmp).
  919. */
  920.  
  921. int in_vector(str)
  922. char *str;
  923. {
  924.     extern int n_keywords;
  925.     extern char *c_keywords[];
  926.     register int n = n_keywords;
  927.     register char **K = c_keywords;
  928.     register int n1, t;
  929.  
  930.     do {
  931.         n1 = n >> 1;
  932.         if (!(t = strcmp(str, K[n1])))
  933.             return K - c_keywords + n1;
  934.         if (t < 0)
  935.             n = n1;
  936.         else {
  937.             n -= ++n1;
  938.             K += n1;
  939.             }
  940.         }
  941.         while(n > 0);
  942.  
  943.     return NOT_IN_VECTOR;
  944.     } /* in_vector */
  945.  
  946.  
  947. int is_negatable (Const)
  948. Constp Const;
  949. {
  950.     int retval = 0;
  951.     if (Const != (Constp) NULL)
  952.     switch (Const -> vtype) {
  953.         case TYSHORT:
  954.             retval = Const -> Const.ci >= -BIGGEST_SHORT;
  955.             break;
  956.         case TYLONG:
  957.             retval = Const -> Const.ci >= -BIGGEST_LONG;
  958.             break;
  959.         case TYREAL:
  960.         case TYDREAL:
  961.         case TYCOMPLEX:
  962.         case TYDCOMPLEX:
  963.             retval = 1;
  964.             break;
  965.         case TYLOGICAL:
  966.         case TYCHAR:
  967.         case TYSUBR:
  968.         default:
  969.             retval = 0;
  970.             break;
  971.     } /* switch */
  972.  
  973.     return retval;
  974. } /* is_negatable */
  975.  
  976. backup(fname, bname)
  977.  char *fname, *bname;
  978. {
  979.     FILE *b, *f;
  980.     static char couldnt[] = "Couldn't open %.80s";
  981.  
  982.     if (!(f = fopen(fname, binread))) {
  983.         warn1(couldnt, fname);
  984.         return;
  985.         }
  986.     if (!(b = fopen(bname, binwrite))) {
  987.         warn1(couldnt, bname);
  988.         return;
  989.         }
  990.     ffilecopy(f, b);
  991.     fclose(f);
  992.     fclose(b);
  993.     }
  994.  
  995.  
  996. /* struct_eq -- returns YES if structures have the same field names and
  997.    types, NO otherwise */
  998.  
  999. int struct_eq (s1, s2)
  1000. chainp s1, s2;
  1001. {
  1002.     struct Dimblock *d1, *d2;
  1003.     Constp cp1, cp2;
  1004.  
  1005.     if (s1 == CHNULL && s2 == CHNULL)
  1006.     return YES;
  1007.     for(; s1 && s2; s1 = s1->nextp, s2 = s2->nextp) {
  1008.     register Namep v1 = (Namep) s1 -> datap;
  1009.     register Namep v2 = (Namep) s2 -> datap;
  1010.  
  1011.     if (v1 == (Namep) NULL || v1 -> tag != TNAME ||
  1012.         v2 == (Namep) NULL || v2 -> tag != TNAME)
  1013.         return NO;
  1014.  
  1015.     if (v1->vtype != v2->vtype || v1->vclass != v2->vclass
  1016.         || strcmp(v1->fvarname, v2->fvarname))
  1017.         return NO;
  1018.  
  1019.     /* compare dimensions (needed for comparing COMMON blocks) */
  1020.  
  1021.     if (d1 = v1->vdim) {
  1022.         if (!(cp1 = (Constp)d1->nelt) || cp1->tag != TCONST)
  1023.             return NO;
  1024.         if (!(d2 = v2->vdim))
  1025.             if (cp1->Const.ci == 1)
  1026.                 continue;
  1027.             else
  1028.                 return NO;
  1029.         if (!(cp2 = (Constp)d2->nelt) || cp2->tag != TCONST
  1030.         ||  cp1->Const.ci != cp2->Const.ci)
  1031.             return NO;
  1032.         }
  1033.     else if ((d2 = v2->vdim) && (!(cp2 = (Constp)d2->nelt)
  1034.                 || cp2->tag != TCONST
  1035.                 || cp2->Const.ci != 1))
  1036.         return NO;
  1037.     } /* while s1 != CHNULL && s2 != CHNULL */
  1038.  
  1039.     return s1 == CHNULL && s2 == CHNULL;
  1040. } /* struct_eq */
  1041.