home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / c / tools / make / nmake / reader.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-07-21  |  13.4 KB  |  491 lines

  1. /* read the makefile, and generate the linked lists */
  2. #include <stdio.h>
  3. #include "make.h"
  4.  
  5. #if MSC
  6. #include <ctype.h>
  7. #endif
  8.  
  9. #define DONE 1
  10. #define ADEFN 2
  11. #define ARULE 3
  12. #define AMACRO 4
  13.  
  14. #if LC
  15. extern int _stack;
  16. #endif
  17.  
  18. /* externals, all defined in make.c */
  19. extern struct macrec *maclist;
  20. extern struct defnrec *defnlist;
  21. extern struct llist *dolist;
  22. extern struct rulerec *rulelist;
  23. extern int no_file,linecont;
  24. long getmodified();
  25. char *get_mem(),*mov_in();
  26.  
  27.  
  28.  
  29. /* local variables */
  30. FILE *fil;
  31. char *fword,*restline,line[INMAX],backup[INMAX];
  32. char *frule;
  33. struct llist *fhowto,*howp3;
  34. struct llist *fdeps,*deprec3;
  35. struct macrec *macp,*macp2;
  36. struct rulerec *rulep,*rulep2;
  37. struct defnrec *defnp;
  38. int sending,def_ready,gdone,rule_send,rule_ready;
  39. struct llist  *targ,*q_how,*q_dep,*targ2;
  40.  
  41. readmakefile(s)
  42. char *s;
  43. {
  44. int i,k;
  45.  
  46.     /* open the file */
  47.     if ( strcmp(s,"-") == 0 ) fil = stdin;
  48.     else if ( (fil = fopen(s,"r")) == NULL) {
  49.     error("couldn't open '%s'.",s);
  50.     return;
  51.     }
  52.  
  53.     /* initialise getnxt() */
  54.     sending = def_ready = gdone = rule_send = rule_ready = FALSE;
  55.     targ = q_how = q_dep = NULL;
  56.     if (getline(fil, backup) == FALSE)
  57.        panic("Empty Makefile");
  58.  
  59.  
  60.     /* getnxt() parses the next line, and returns the parts */
  61.     while (TRUE) switch( getnxt() ){
  62.  
  63.     case DONE: return;
  64.  
  65.     case AMACRO:      /* add a macro to the list */
  66.  
  67.         /** get space */
  68.         macp = (struct macrec *)get_mem((unsigned) sizeof(struct macrec));
  69.         if (maclist == NULL)
  70.             maclist = macp;
  71.         else {
  72.             macp2 = maclist;
  73.             while (macp2->nextmac != NULL)
  74.                  macp2 = macp2->nextmac;
  75.             macp2->nextmac = macp;
  76.          }
  77.          uppercase(fword);
  78.          macp->name = mov_in(fword);
  79.          macp->mexpand = mov_in(restline);
  80.          macp->nextmac = NULL;
  81.          break;
  82.  
  83.     case ARULE:      /* add a rule to the list */
  84.  
  85.         rulep = (struct rulerec *)get_mem(sizeof(struct rulerec));
  86.         if (rulelist == NULL)
  87.             rulelist = rulep;
  88.         else{
  89.             rulep2 = rulelist;
  90.             while (rulep2->nextrule != NULL)
  91.                rulep2 = rulep2->nextrule;
  92.             rulep2->nextrule = rulep;
  93.         }
  94.         /*fword[0] is defined to be a period*/
  95.         for (i=1; notnull(fword[i]) ;i++)
  96.             if ( fword[i] == '.' ) break;
  97.         if ( i == strlen(fword) )  panic("Bad rule '%s'",fword);
  98.         fword[i] = NUL;
  99.         rulep->dep = mov_in(fword + 1); /*don't save the preceding '.' */
  100.         /* be sure object extension has no spaces */
  101.         for ( k = i+1 ; notnull(fword[k]) && !isspace(fword[k]) ; k++ )
  102.         ;/*NOP*/
  103.         if ( isspace(fword[k]) ) fword[k] = NUL;
  104.         rulep->targ = mov_in(fword + i + 1);
  105.         rulep->rule = fhowto;
  106.         rulep->nextrule = NULL;
  107.         break;
  108.  
  109.     case ADEFN:     /* add a definition */
  110.  
  111.         if (no_file) {      /*if no target specified on command line... */
  112.             add_do(fword);  /*push this target on to do list */
  113.             no_file = FALSE;
  114.         }
  115.         /* getnxt() returns target ( fword ) , pointer to expanded howto
  116.            list ( fhowto ) and pointer to expanded depends ( fdeps )
  117.         */
  118.         if ( defnlist == NULL ) {
  119.             add_defn();   /* add the current definition to the end */
  120.     }
  121.         else {
  122.             defnp = defnlist;
  123.             while ( defnp != NULL ) {
  124.                 if (strcmp(defnp->name,fword) == 0) break;
  125.                 else defnp = defnp->nextdefn;
  126.         }
  127.             if ( defnp == NULL ) {
  128.                 /* target not currently in list */
  129.                 add_defn();
  130.         }
  131.             else {
  132.                 /* target is on list, add new depends and howtos */
  133.                 if (defnp->dependson == NULL)
  134.                     defnp->dependson = fdeps;
  135.                 else {
  136.                     deprec3 = defnp->dependson;
  137.                     while (deprec3->next != NULL)
  138.                          deprec3 = deprec3->next;
  139.                     deprec3->next = fdeps;
  140.         }
  141.                 /* add new howtos */
  142.                 if (defnp->howto == NULL)
  143.                     defnp->howto = fhowto;
  144.                 else {
  145.                     howp3 = defnp->howto;
  146.                     while ( howp3->next != NULL)
  147.                          howp3 = howp3->next;
  148.                     howp3->next = fhowto;
  149.         }
  150.         }
  151.     }
  152.         break;
  153.     }
  154. }
  155.  
  156. add_defn()     /* add a new definition */
  157. {
  158. struct defnrec *ptr,*ptr2;
  159.     ptr = (struct defnrec *)get_mem(sizeof(struct defnrec));
  160.     ptr->name = fword;
  161.     ptr->uptodate = FALSE;
  162.     ptr->modified = getmodified(fword,DEPENDANT);
  163.     ptr->dependson = fdeps;
  164.     ptr->howto = fhowto;
  165.     ptr->nextdefn = NULL;
  166.     if ( defnlist == NULL ) {
  167.     defnlist = ptr;
  168.     return;
  169.     }
  170.     else {
  171.     ptr2 = defnlist;
  172.     while ( ptr2->nextdefn != NULL )
  173.             ptr2 = ptr2->nextdefn;
  174.     ptr2->nextdefn = ptr;
  175.     }
  176. }
  177.  
  178. getnxt()
  179. {
  180. int pos,mark,parsed;
  181. char exp_line[INMAX];
  182. struct llist *mkllist(),*mkexphow(),*mkexpdep(),*q_how2,*q_how3;
  183.  
  184.   while ( TRUE ) {
  185.  
  186.    /* if we are currently sending targets */
  187.    if ( sending ) {
  188.         if ( targ2->next == NULL) {
  189.             sending = def_ready = FALSE;
  190.         }
  191.         fword = mov_in(targ2->name);
  192.         fhowto = mkexphow(q_how,targ2->name,REPT_ERR);
  193.         fdeps = mkexpdep(q_dep,targ2->name);
  194.         targ2 = targ2->next;
  195.         return ( ADEFN );
  196.     }
  197.     
  198.     /* are we sending a rule? */
  199.     if ( rule_send ) {
  200.         fword = frule;
  201.         fhowto = mkexphow(q_how,(char *)NULL,IGN_ERR); /* target == NULL -> don't expand */
  202.         rule_send = rule_ready = FALSE;
  203.         return( ARULE );
  204.     }
  205.     
  206.     if ( gdone ) return ( DONE );
  207.     /* if we are not currently sending... */
  208.  
  209.     /* load the next line into 'line' ( which may be backed-up ) */
  210.     if ( backup[0] != NUL ) {
  211.         strcpy(line,backup);
  212.         backup[0] = NUL;
  213.     }
  214.     else {
  215.         if ( getline(fil,line) == FALSE ) {
  216.             if ( def_ready ) sending = TRUE;
  217.             if ( rule_ready ) rule_send = TRUE;
  218.             gdone = TRUE;
  219.             continue;  /* break the loop, and flush any definitions */
  220.         }
  221.     }
  222.     parsed = FALSE;
  223.  
  224.     /* check for rule, and begin loading it if there */
  225.     if (line[0] == '.'){
  226.         /* found a rule */
  227.         for (pos = 0 ; line[pos] != ':' && notnull(line[pos]) ; pos++)
  228.             if (isspace(line[pos])) continue;
  229.         if (isnull(line[pos]))
  230.            error("rule needs colon separator '%s'",line);
  231.         mark = pos;
  232.         for (pos++ ; line[pos] != ';' && notnull(line[pos]) ; pos++) ;
  233.         if (isnull(line[pos]))
  234.            error("rule needs ';' after ':'-- '%s'",line);
  235.         parsed = TRUE;
  236.         if ( rule_ready || def_ready ) {
  237.             if ( def_ready ) sending = TRUE;
  238.             else rule_send = TRUE;
  239.             strcpy(backup,line); /* push this line, and send what we already have */
  240.         }
  241.         else {
  242.             rule_ready = TRUE;
  243.             line[mark] = NUL;
  244.             frule = mov_in(line);
  245.             free_list(q_how);
  246.             q_how = MkListMem();
  247.             q_how->name = mov_in(line + pos + 1 );
  248.             q_how->next = NULL;
  249.         }
  250.     }
  251.     
  252.     /* check for macro, and return it if there */
  253.     if ( !parsed ) {
  254.         pos = 0;
  255.         while ( line[pos] != '=' &&
  256.                 line[pos] != ':' &&
  257.                 !isspace(line[pos]) &&
  258.                 notnull(line[pos])) pos++;
  259.         mark = pos;
  260.         if (notnull(line[pos]) && line[pos] != ':'){
  261.             /* found a macro */
  262.             if (isspace(line[pos]))
  263.                while (isspace(line[pos]) && notnull(line[pos])) pos++;
  264.             if (isnull(line[pos]))
  265.                panic("bad macro or definition '%s'",line);
  266.             if ( line[pos] == '=' ) {
  267.                 /* found a macro */
  268.                 line[mark] = NUL;
  269.                 fword = line;
  270.                 mark = pos + 1;
  271.                 while ( isspace(line[mark]) ) mark++; /* skip spaces before macro starts */
  272.                 restline = line + mark;
  273.                 return ( AMACRO );
  274.             }
  275.         }
  276.     }
  277.  
  278.  
  279.  
  280.     /* check for and add howto line */
  281.     if ( isspace(line[0]) ) {
  282.     if (!def_ready && !rule_ready)
  283.        error("how-to line without preceeding definition or rule\n'%s'",line);
  284.     for ( pos = 0 ; isspace(line[pos]) ; pos++ ) ;
  285.     q_how2 = MkListMem();
  286.     if ( q_how == NULL ) {
  287.         q_how = q_how2;
  288.     }
  289.     else {
  290.         q_how3 = q_how;
  291.         while ( q_how3->next != NULL )
  292.                 q_how3 = q_how3->next;
  293.         q_how3->next = q_how2;
  294.     }
  295.     q_how2->name = mov_in(line);
  296.     q_how2->next = NULL;
  297.     parsed = TRUE;
  298.     }
  299.  
  300.     
  301.     /* check for definition */
  302.     if (!parsed) {
  303.         pos = 0;
  304.         while ( notnull(line[pos]) && line[pos] != ':') pos++;
  305.         if (line[pos] == ':') {
  306.             /* found a definition */
  307.             parsed = TRUE;
  308.             if (def_ready || rule_ready) {
  309.                 if ( def_ready ) sending = TRUE;
  310.                 else rule_send = TRUE;
  311.                 strcpy(backup,line);
  312.             }
  313.             else {
  314.                /* free up the space used by the previous lists */
  315.                free_list(targ);targ = NULL;
  316.                free_list(q_how);q_how = NULL;
  317.                free_list(q_dep);q_dep = NULL;
  318.                line[pos] = NUL;
  319.                expand(line,exp_line,"",NO_TARG);
  320.                targ2 = targ = mkllist(exp_line);
  321.                q_dep = mkllist(line + pos + 1);
  322.                def_ready = TRUE;
  323.             }
  324.         }
  325.     }
  326.     if (!parsed)
  327.        panic("unable to parse line '%s'",line);
  328.   }
  329. }
  330.  
  331.  
  332.     
  333. /*
  334.    load the next line from 'stream' to 'where' allowing for comment char
  335.    and line continuations 
  336. */
  337. getline(stream,where)
  338. char *where;
  339. FILE *stream;
  340. {
  341. int i,x;
  342.  
  343.     while (fgets(where,INMAX,stream) != NULL) {
  344.         i = strlen(where);
  345.         where[--i] = NUL;  /* null terminate the string ( drop \n ) */
  346.  
  347.         /* terminate stdin input with a '.' */
  348.         if ( (stream == stdin) && (strcmp(where,".") == 0) ) return( FALSE );
  349.  
  350.         /* if line is blank, or begins with # , skip it */
  351.         if (isnull(where[0]) || where[0] == '#')  continue;
  352.  
  353.         /* if the line is only ws, skip it */
  354.         for ( x = 0; isspace(where[x]) && notnull(where[x]) ; x++) ;
  355.         if (isnull(where[x])) continue;
  356.  
  357.         while (where[i-1] == linecont ){
  358.            /*continue reading line if line continuation character*/
  359.            if (fgets(where + i - 1,INMAX,stream) ==  NULL)
  360.                error("end of file before end of line");
  361.            if ( (stream == stdin) && (strcmp(where + i - 1,".\n") == 0) ) 
  362.                error("end of file before end of line");
  363.            i = strlen(where);
  364.            where[--i] = NUL;
  365.         }
  366.         if ( i >= INMAX ) {
  367.             where[INMAX] = NUL;
  368.             panic("line too long\n'%s'",where);
  369.         }
  370.         return ( TRUE );
  371.     }
  372.     return ( FALSE );
  373. }
  374.  
  375.  
  376.  
  377. struct llist *mkllist( s )  /* make a  linked list */
  378. char *s;
  379. {
  380. int i,pos;
  381. char lname[INMAX];
  382. struct llist *ptr,*ptr2,*retval;
  383.  
  384.  
  385.      i = pos = 0;
  386.      retval = NULL;
  387.      while ( TRUE ) {
  388.      while ( notnull(s[pos]) && isspace(s[pos]) ) pos++;
  389.  
  390.      if ( isnull(s[pos]) ) return( retval );
  391.  
  392.      while ( !isspace(s[pos]) && notnull(s[pos]) ) lname[i++] = s[pos++];
  393.  
  394.      /* found something to add */
  395.      ptr = MkListMem();
  396.      if ( retval == NULL ) {
  397.          retval = ptr;
  398.      }
  399.      else {
  400.          ptr2 = retval;
  401.          while ( ptr2->next != NULL )
  402.                  ptr2 = ptr2->next;
  403.          ptr2->next = ptr;
  404.      }
  405.      lname[i] = NUL;
  406.      ptr->name = mov_in(lname);
  407.      ptr->next = NULL;
  408.      i = 0;
  409.      }
  410. }
  411.  
  412.  
  413. struct llist *mkexphow(head,target,eflag) /* make an expanded linked list for how */
  414. struct llist *head;
  415. char *target;
  416. int eflag;
  417. {
  418. struct llist *p,*p2,*retval;
  419. char temp[INMAX];
  420.  
  421.    if ( head == NULL ) {
  422.        return ( NULL );
  423.    }
  424.  
  425.    retval = NULL;
  426.    while ( head != NULL ) {
  427.       
  428.       if ( target != NULL ) expand(head->name,temp,target,eflag);
  429.       else strcpy(temp,head->name);
  430.       p = MkListMem();      
  431.       p->name = mov_in(temp);
  432.       p->next = NULL;
  433.  
  434.       if ( retval == NULL ) retval = p;
  435.       else {
  436.       p2 = retval;
  437.       while ( p2->next != NULL )
  438.           p2 = p2->next;
  439.       p2->next = p;
  440.       }
  441.       head = head->next;
  442.    }
  443.    return( retval );
  444. }
  445.  
  446. struct llist *mkexpdep(head,target)  /* make an expanded linked list for dep*/
  447. struct llist *head;
  448. char *target;
  449. {
  450. struct llist *p,*p2,*p3,*retval;
  451. char temp[INMAX];
  452.  
  453.  if ( head == NULL ) {
  454.       return ( NULL );
  455.  }
  456.  
  457.  retval = NULL;
  458.  while ( head != NULL ) {
  459.       
  460.    expand(head->name,temp,target,REPT_ERR);
  461.    p3 = mkllist(temp);
  462.    while ( p3 != NULL ) {
  463.       p = MkListMem();      
  464.       p->name = mov_in(p3->name);
  465.       p->next = NULL;
  466.  
  467.       if ( retval == NULL ) retval = p;
  468.       else {
  469.       p2 = retval;
  470.       while ( p2->next != NULL )
  471.           p2 = p2->next;
  472.       p2->next = p;
  473.       }
  474.       p3 = p3->next;
  475.    }
  476.    free_list(p3);
  477.    head = head->next;
  478.  }
  479.  return( retval );
  480. }
  481.  
  482.  
  483. free_list(ptr)   /* kill a linked list */
  484. struct llist *ptr;
  485. {
  486.     if       ( ptr == NULL )       return;
  487.     else if  ( ptr->next == NULL ) free(ptr);
  488.     else                           free_list(ptr->next);
  489. }
  490.     
  491.