Beispiel #1
0
int parse_line(struct prog_info *pi, char *line) 
{
	char *ptr=NULL;
	int k;
	int flag=0, i;
	int global_label = False;
	char temp[LINEBUFFER_LENGTH];
	struct label *label = NULL;
	struct macro_call *macro_call;

	while(IS_HOR_SPACE(*line)) line++;			/* At first remove leading spaces / tabs */
	if(IS_END_OR_COMMENT(*line))				/* Skip comment line or empty line */
		return(True);
								/* Filter out .stab debugging information */
								/* .stabs sometimes contains colon : symbol - might be interpreted as label */
	if(*line == '.') {					/* minimal slowdown of existing code */
		if(strncmp(temp,".stabs ",7) == 0 ) {		/* compiler output is always lower case */
			strcpy(temp,line);			/* TODO : Do we need this temp variable ? Please check */
			return parse_stabs( pi, temp );
		}
		if(strncmp(temp,".stabn ",7) == 0 ) {
			strcpy(temp,line);
			return parse_stabn( pi, temp );
		}
	}
								/* Meta information translation */
	ptr=line;
	k=0;
	while((ptr=strchr(ptr, '%')) != NULL) {
		if(!strncmp(ptr, "%MINUTE%", 8) ) {		/* Replacement always shorter than tag -> no length check */
			k=strftime(ptr,3,"%M", localtime(&pi->time));
			strcpy(ptr+k,ptr+8); 
			ptr+=k;
			continue;
		}
		if(!strncmp(ptr, "%HOUR%", 6) ) {			
			k=strftime(ptr,3,"%H", localtime(&pi->time));
			strcpy(ptr+k,ptr+6); 
			ptr+=k;
			continue;
		}
		if(!strncmp(ptr, "%DAY%", 5) ) {
			k=strftime(ptr,3,"%d", localtime(&pi->time));
			strcpy(ptr+k,ptr+5); 
			ptr+=k;
			continue;
		}
		if(!strncmp(ptr, "%MONTH%", 7) ) {
			k=strftime(ptr,3,"%m", localtime(&pi->time));
			strcpy(ptr+k,ptr+7); 
			ptr+=k;
			continue;
		}
		if(!strncmp(ptr, "%YEAR%", 6) ) {
			k=strftime(ptr,5,"%Y", localtime(&pi->time));
			strcpy(ptr+k,ptr+6); 
			ptr+=k;
			continue;
		}
		ptr++;
	}

//	if(pi->pass == PASS_2)		// TODO : Test
//		strcpy(pi->list_line, line);

	strcpy(pi->fi->scratch,line);

	for(i = 0; IS_LABEL(pi->fi->scratch[i]) || (pi->fi->scratch[i] == ':'); i++)
		if(pi->fi->scratch[i] == ':') {	/* it is a label */
			pi->fi->scratch[i] = '\0';
			if(pi->pass == PASS_1) {
				for(macro_call = pi->macro_call; macro_call; macro_call = macro_call->prev_on_stack) {
					for(label = pi->macro_call->first_label; label; label = label->next) {
						if(!nocase_strcmp(label->name, &pi->fi->scratch[0])) {
							print_msg(pi, MSGTYPE_ERROR, "Can't redefine local label %s", &pi->fi->scratch[0]);
							break;
						}
					}
				}
				if(test_label(pi,&pi->fi->scratch[0],"Can't redefine label %s")!=NULL) 
					break;
				if(test_variable(pi,&pi->fi->scratch[0],"%s have already been defined as a .SET variable")!=NULL) 
					break;
				if(test_constant(pi,&pi->fi->scratch[0],"%s has already been defined as a .EQU constant")!=NULL) 
					break;
				label = malloc(sizeof(struct label));
				if(!label) {
					print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
					return(False);
				}
				label->next = NULL;
				label->name = malloc(strlen(&pi->fi->scratch[0]) + 1);
				if(!label->name) {
					print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
					return(False);
				}
				strcpy(label->name, &pi->fi->scratch[0]);
				switch(pi->segment) {
					case SEGMENT_CODE:
						label->value = pi->cseg_addr;
						break;
					case SEGMENT_DATA:
						label->value = pi->dseg_addr;
						break;
					case SEGMENT_EEPROM:
						label->value = pi->eseg_addr;
						break;
				}
				if(pi->macro_call && !global_label) {
					if(pi->macro_call->last_label)
						pi->macro_call->last_label->next = label;
				  	else
						pi->macro_call->first_label = label;
				  	pi->macro_call->last_label = label;
				} else {
					if(pi->last_label)
				  		pi->last_label->next = label;
					else
						pi->first_label = label;
					pi->last_label = label;
				}
			} 
			i++;
			while(IS_HOR_SPACE(pi->fi->scratch[i]) && !IS_END_OR_COMMENT(pi->fi->scratch[i])) i++;
			if(IS_END_OR_COMMENT(pi->fi->scratch[i])) {
				if((pi->pass == PASS_2) && pi->list_on) { // Diff tilpassing
					fprintf(pi->list_file, "          %s\n", pi->list_line);
					pi->list_line = NULL;
				}
				return(True);
			}
			strcpy(pi->fi->scratch, &pi->fi->scratch[i]);
			break;
		}

#if 0
	if(pi->fi->scratch[0] == '.') {
#else
	if((pi->fi->scratch[0] == '.') || (pi->fi->scratch[0] == '#')) {
#endif
		pi->fi->label = label;
		flag = parse_directive(pi);
		if((pi->pass == PASS_2) && pi->list_on && pi->list_line) { // Diff tilpassing 
  			fprintf(pi->list_file, "          %s\n", pi->list_line);
			pi->list_line = NULL;
		}
		return(flag);
	} else {
		return parse_mnemonic(pi);
	}
}


/*
 * Get the next token, and terminate the last one.
 * Termination identifier is specified.
 */

char *get_next_token(char *data, int term)
{
	int i = 0, j, anti_comma = False;
	switch(term) {
		case TERM_END:
//			while(!IS_END_OR_COMMENT(data[i])) i++; 	Problems with 2. operand == ';'
			while( ((data[i] != ',') || anti_comma) && !(((data[i] == ';') && !anti_comma) || IS_ENDLINE(data[i])) ) {
				if((data[i] == '\'') || (data[i] == '"')) 
					anti_comma = anti_comma ? False : True;
				i++;
			}
			break;
		case TERM_SPACE:
			while(!IS_HOR_SPACE(data[i]) && !IS_END_OR_COMMENT(data[i])) i++;
			break;
		case TERM_DASH:
			while((data[i] != '-') && !IS_END_OR_COMMENT(data[i])) i++;
			break;
		case TERM_COLON:
			while((data[i] != ':') && !IS_ENDLINE(data[i])) i++;
			break;
		case TERM_DOUBLEQUOTE:
			while((data[i] != '"') && !IS_ENDLINE(data[i])) i++;
			break;
		case TERM_COMMA:
			while(((data[i] != ',') || anti_comma) && !(((data[i] == ';') && !anti_comma) || IS_ENDLINE(data[i])) ) {
				if((data[i] == '\'') || (data[i] == '"')) 
					anti_comma = anti_comma ? False : True;
				i++;
			}
			break;
		case TERM_EQUAL:
			while((data[i] != '=') && !IS_END_OR_COMMENT(data[i])) i++;
			break;
	}
	if(IS_END_OR_COMMENT(data[i])) {
		data[i--] = '\0';
		while(IS_HOR_SPACE(data[i])) data[i--] = '\0';
		return(0);
	}
	j = i - 1;
	while(IS_HOR_SPACE(data[j])) data[j--] = '\0';
	data[i++] = '\0';
	while(IS_HOR_SPACE(data[i]) && !IS_END_OR_COMMENT(data[i])) i++;
	if(IS_END_OR_COMMENT(data[i]))
		return(0);
	return(&data[i]);
}
Beispiel #2
0
void loadlgf(int mode)
{
   FILE *ps;
   char inname[150], temp[500], *pdchar;
   char **signals;
   short *signets;
   objectptr *libobj;
   genericptr *iolabel;
   int i, sigs;

   sscanf(_STR, "%149s", inname);

   ps = fopen(inname, "r");
   if (ps == NULL) {
      sprintf(inname, "%s.lgf", _STR);
      ps = fopen(inname, "r");
      if (ps == NULL) {
	 sprintf(inname, "%s.lfo", _STR);
	 ps = fopen(inname, "r");
	 if (ps == NULL) {
	    Wprintf("Can't open LGF file %s", inname);
	    return;
         }
      }
   }

   /* for PostScript file, remove ".lgf" or ".lfo" (to be replaced with ".ps") */

   if ((pdchar = strstr(inname, ".l")) != NULL) *pdchar = '\0';

   Wprintf("Loaded file: %s", inname);

   /* Make sure that LGF object library has been loaded by loading it now. */

   if (NameToLibrary(LGF_LIB) < 0) {
      int ilib;
      strcpy(_STR, LGF_LIB);
      ilib = createlibrary(FALSE);
      loadlibrary(ilib);
   }
   
   /* Read header information */

   if (fgets(temp, 149, ps) == NULL) {
      Wprintf("Error: end of file.");
      return;
   }
   for (pdchar = temp; *pdchar != '-' && *pdchar != '\n'; pdchar++);
   if (*pdchar == '\n') {
      Wprintf("Not an LGF file?");
      return;
   }
   if (*(++pdchar) != '5') {
      Wprintf("Don't know how to read version %c.", *pdchar);
      return;
   }
   if (fgets(temp, 149, ps) == NULL) {
      Wprintf("Error: end of file.");
      return;
   }
   for (pdchar = temp; *pdchar != 'f' && *pdchar != '\n'; pdchar++);
   for (; *pdchar != 's' && *pdchar != '\n'; pdchar++);
   if (*pdchar == '\n') {
      Wprintf("Something wrong with the LGF file?");
      return;
   }

   /* Done with header. . . okay to clear current page now unless importing */

   if (mode == 0) {
      reset(topobject, NORMAL);
      pagereset(areawin->page); 
   }

   /* Set up filename and object (page) name */

   xobjs.pagelist[areawin->page]->filename = (char *) realloc (
      xobjs.pagelist[areawin->page]->filename, (strlen(inname) + 1) * sizeof(char));
   strcpy(xobjs.pagelist[areawin->page]->filename, inname);

   /* If the filename has a path component, use only the root */

   if ((pdchar = strrchr(inname, '/')) != NULL)
      sprintf(topobject->name, "%s", pdchar + 1);
   else
      sprintf(topobject->name, "%s", inname);

   renamepage(areawin->page);
   printname(topobject);

   /* Read objects */

   for(;;) {
      char *lineptr, keyptr, tmpstring[256];
      int dval;
      short pvalx, pvaly, pvalx2, pvaly2;

      if (fgets(temp, 499, ps) == NULL) break;		/* End-Of-File */

      /* ignore whitespace */
      for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
      if (*lineptr == '\n') continue;  /* ignore blank lines */
      switch(keyptr = *lineptr) {

	 case '#':	/* comment */
	    break;

	 case 'n':	/* nodes */
	    sscanf(++lineptr, "%d", &dval); 	    
	    for (i = 0; i < dval; i++) {
	       do {
	          if (fgets(temp, 499, ps) == NULL) {
		     Wprintf("End of file in node section");
		     return;
	          }
      	          for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
	       } while (*lineptr == '\n');
	    }
	    break;

	 case 's': 	/* signal names --- save for future reference */

	    sscanf(++lineptr, "%d", &sigs);
	    signals = (char **) malloc(sigs * sizeof(char *));
	    signets = (short *) malloc(sigs * sizeof(short));
	    for (i = 0; i < sigs; i++) {
	       do {
	          if (fgets(temp, 499, ps) == NULL) {
		     Wprintf("End of file in signal section");
		     return;
	          }
      	          for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
	       } while (*lineptr == '\n');
	       
	       sscanf(lineptr, "%hd %249s", &signets[i], tmpstring);

	       signals[i] = (char *)malloc((strlen(tmpstring) + 1) * sizeof(char));
	       sprintf(signals[i], "%s", tmpstring);
            }
	    break;
	 
	 case 'l': {	/* labels */

	    labelptr *newlabel;
	    char *tstrp;

	    sscanf(++lineptr, "%d", &dval);
	    for (i = 0; i < dval; i++) {
	       do {
	          if (fgets(temp, 499, ps) == NULL) {
		     Wprintf("End of file in signal section");
		     return;
	          }
      	          for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
	       } while (*lineptr == '\n');
	       
	       /* Allocate label, and put node number into X value, to be replaced */
	       /* Flag it using an inappropriate rotation value (= 500) */

	       sscanf(lineptr, "%hd %hd", &pvalx, &pvaly);

	       /* Get rid of newline character, if any */

	       ridnewline(lineptr);

	       /* forward to the label part of the input line */

	       tstrp = lineptr - 1;
	       while (isdigit(*(++tstrp)));
	       while (isspace(*(++tstrp)));
	       while (isdigit(*(++tstrp)));
	       while (isspace(*(++tstrp)));
	       while (isdigit(*(++tstrp)));
	       while (isspace(*(++tstrp)));

	       if (tstrp != NULL) {	/* could be a blank line */
		  stringpart *strptr;

		  NEW_LABEL(newlabel, topobject);

		  labeldefaults(*newlabel, False, xmat(pvalx), ymat(pvaly));
	          (*newlabel)->justify = TOP | NOTBOTTOM;
		  (*newlabel)->color = DEFAULTCOLOR;
		  (*newlabel)->string->data.font = 0;
		  strptr = makesegment(&((*newlabel)->string), NULL);
		  strptr->type = TEXT_STRING;
		  strptr->data.string = (char *)malloc(1 + strlen(tstrp));
		  strcpy(strptr->data.string, tstrp);
		  (*newlabel)->pin = NORMAL;
	       }
            }}
	    break;

	case 'w': {	/* wires, implemented as single-segment polygons */
	    polyptr *newwire;
	    XPoint  *tmppnts;

	    sscanf(++lineptr, "%d", &dval);
	    for (i = 0; i < dval; i++) {
	       do {
	          if (fgets(temp, 499, ps) == NULL) {
		     Wprintf("End of file in wire section");
		     return;
	          }
      	          for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
	       } while (*lineptr == '\n');

	       /* Allocate wire */

	       NEW_POLY(newwire, topobject);

	       sscanf(lineptr, "%hd %hd %hd %hd", &pvalx, &pvaly, &pvalx2, &pvaly2);
	       (*newwire)->number = 2;
	       (*newwire)->points = (XPoint *)malloc(2 * sizeof(XPoint));
	       (*newwire)->width = 1.0;
	       (*newwire)->style = UNCLOSED;
	       (*newwire)->color = DEFAULTCOLOR;
	       (*newwire)->passed = NULL;
	       tmppnts = (*newwire)->points;
	       tmppnts->x = xmat(pvalx);
	       tmppnts->y = ymat(pvaly);
	       (++tmppnts)->x = xmat(pvalx2);
	       tmppnts->y = ymat(pvaly2);

	    }}
	    break;

	case 'p': 	/* solder dot */
	    sscanf(++lineptr, "%d", &dval);
	    for (i = 0; i < dval; i++) {
	       do {
	          if (fgets(temp, 499, ps) == NULL) {
		     Wprintf("End of file in solder dot section");
		     return;
	          }
      	          for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
	       } while (*lineptr == '\n');

	       /* Allocate arc */

	       sscanf(lineptr, "%hd %hd", &pvalx, &pvaly);
	       drawdot(xmat(pvalx), ymat(pvaly));
	    }
	    break;

	case 'b': {	/* boxes */
	    polyptr *newpoly;
	    pointlist newpoints;

	    sscanf(++lineptr, "%d", &dval);
	    for (i = 0; i < dval; i++) {
	       do {
	          if (fgets(temp, 499, ps) == NULL) {
		     Wprintf("End of file in box section");
		     return;
	          }
      	          for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
	       } while (*lineptr == '\n');

	       NEW_POLY(newpoly, topobject);

	       (*newpoly)->style = DASHED;
	       (*newpoly)->color = DEFAULTCOLOR;
	       (*newpoly)->width = 1.0;
	       (*newpoly)->number = 4;
               (*newpoly)->points = (pointlist) malloc(4 * sizeof(XPoint));
	       (*newpoly)->passed = NULL;

               newpoints = (*newpoly)->points;
	       sscanf(lineptr, "%hd %hd %hd %hd", &pvalx, &pvaly, &pvalx2, &pvaly2);
	       newpoints->x = xmat(pvalx);
	       newpoints->y = ymat(pvaly);
	       (newpoints + 1)->x = xmat(pvalx2);
	       (newpoints + 2)->y = ymat(pvaly2);

	       (newpoints + 2)->x = (newpoints + 1)->x;
	       (newpoints + 3)->x = newpoints->x;
	       (newpoints + 1)->y = newpoints->y;
	       (newpoints + 3)->y = (newpoints + 2)->y;
	    }}
	    break;

	case 'g': {	/* gates */

	    objinstptr *newinst;
	    labelptr *newlabel;
	    int j, k, hval, flip;

	    sscanf(++lineptr, "%d", &dval);
	    for (i = 0; i < dval; i++) {
	       do {
	          if (fgets(temp, 499, ps) == NULL) {
		     Wprintf("End of file in gates section");
		     return;
	          }
		  for (lineptr = temp; *lineptr != '\n'; lineptr++); *lineptr = '\0';
      	          for (lineptr = temp; isspace(*lineptr) && *lineptr != '\0'; lineptr++);
	       } while (*lineptr == '\0');

	       /* double loop through user libraries */

	       for (j = 0; j < xobjs.numlibs; j++) {
		  for (k = 0; k < xobjs.userlibs[j].number; k++) {
		     libobj = xobjs.userlibs[j].library + k;
	             if (!strcmp(lineptr, (*libobj)->name)) break;
		  }
	          if (k < xobjs.userlibs[j].number) break;
	       }
	       strcpy(tmpstring, lineptr);

	       /* read gate definition */

	       if (fgets(temp, 499, ps) == NULL) {
		  Wprintf("End of file during gate read");
		  return;
	       }
      	       for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);

	       if (j < xobjs.numlibs || k < xobjs.userlibs[xobjs.numlibs - 1].number) {

		  NEW_OBJINST(newinst, topobject);

	          sscanf(lineptr, "%hd %hd %hd %*d %*d %*d %d", &pvalx, &pvaly,
			&pvalx2, &hval); 

		  flip = (pvalx2 >= 4) ? 1 : 0;
		  if (!strcmp(tmpstring, "FROM")) flip = 1 - flip;

		  (*newinst)->position.x = xmat(pvalx);
		  (*newinst)->position.y = ymat(pvaly);
		  (*newinst)->scale = 1.0;
		  (*newinst)->color = DEFAULTCOLOR;
		  (*newinst)->params = NULL;
	          (*newinst)->passed = NULL;

		  if (pvalx2 & 0x01) pvalx2 ^= 0x02;
                  if (pvalx2 >= 4) (*newinst)->rotation = -(((pvalx2 - 4) * 90) + 1);
                  else (*newinst)->rotation = (pvalx2 * 90) + 1;
		  (*newinst)->thisobject = *libobj;
		  (*newinst)->bbox.lowerleft.x = (*libobj)->bbox.lowerleft.x;
		  (*newinst)->bbox.lowerleft.y = (*libobj)->bbox.lowerleft.y;
		  (*newinst)->bbox.width = (*libobj)->bbox.width;
		  (*newinst)->bbox.height = (*libobj)->bbox.height;

	          /* Add label to "TO" and "FROM" */

	          if (!strcmp(tmpstring, "FROM") || !strcmp(tmpstring, "TO")) {
	   	     int nval;

		     hval--;
		     fgets(temp, 499, ps);
		     sscanf(temp, "%d", &nval);

		     for (k = 0; k < sigs; k++)
		        if (signets[k] == nval) {
			   stringpart *strptr;

			   NEW_LABEL(newlabel, topobject);
			   /* reconnect newinst if displaced by realloc() */
			   newinst = (objinstptr *)(topobject->plist
				+ topobject->parts - 2);

			   labeldefaults(*newlabel, False, (*newinst)->position.x,
				(*newinst)->position.y);
			   (*newlabel)->color = DEFAULTCOLOR;
			   (*newlabel)->pin = LOCAL;
			   (*newlabel)->color = LOCALPINCOLOR;
			   if (!strcmp(tmpstring, "TO"))
			      (*newlabel)->position.x += ((flip) ? 48 : -48);
			   else
			      (*newlabel)->position.x += ((flip) ? 54 : -54);

			   (*newlabel)->justify = NOTBOTTOM;
			   if (flip) (*newlabel)->justify |= (RIGHT | NOTLEFT);
			   (*newlabel)->string->data.font = 0;
			   strptr = makesegment(&((*newlabel)->string), NULL);
			   strptr->type = TEXT_STRING;
			   strptr->data.string = (char *)malloc(1 + strlen(signals[k]));
			   strcpy(strptr->data.string, signals[k]);
			   break;
		        }
	          }
	       }

	       /* read through list of attributes */

	       else {
	          sscanf(lineptr, "%*d %*d %*d %*d %*d %*d %d", &hval);
	          Wprintf("No library object %s", tmpstring);
	       }

	       for (j = 0; j < hval + 1; j++) {
	          if (fgets(temp, 499, ps) == NULL) {
		     Wprintf("Unexpected end of file");
		     return;
	          }
	       }
	       /* read to next blank line */
	       do {
		  if (fgets(temp, 499, ps) == NULL) break;
      	          for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
	       } while (*lineptr != '\n');
	    }}
	    break;

	case 'h': {	/* history */
	    int j, hval;

	    sscanf(++lineptr, "%d", &dval);
	    for (i = 0; i < dval; i++) {
	       do {
	          if (fgets(temp, 499, ps) == NULL) {
		     Wprintf("End of file in history section");
		     return;
	          }
      	          for (lineptr = temp; isspace(*lineptr) && *lineptr != '\n'; lineptr++);
	       } while (*lineptr == '\n');

	       /* read through history */

	       sscanf(lineptr, "%*d %d", &hval);
	       for (j = 0; j < hval; j++)
	          if (fgets(temp, 499, ps) == NULL) {
		     Wprintf("Unexpected end of file");
		     return;
	          }
	    }}
	    break;

	case '.':	/* blank, don't use for EOF */
	    break;

	default:
	    Wprintf("Don't understand statement '%c'", *lineptr);
	    break;
      }
   }

   /* check for unattached labels and delete them */

   for (iolabel = topobject->plist; iolabel < topobject->plist +
	   topobject->parts; iolabel++)
      if (IS_LABEL(*iolabel)) {
         if (TOLABEL(iolabel)->rotation == 500) {
	    genericptr *tmplabel;

	    free(TOLABEL(iolabel)->string);
	    free(*iolabel);
            for (tmplabel = iolabel + 1; tmplabel < topobject->plist +
                topobject->parts; tmplabel++) *(tmplabel - 1) = *tmplabel;
            topobject->parts--;
	    iolabel--;
	 }
      }

   calcbbox(areawin->topinstance);
   centerview(areawin->topinstance);

   for (i = 0; i < sigs; i++) free(signals[i]);
   free(signals);
   free(signets);
}
Beispiel #3
0
int read_macro(struct prog_info *pi, char *name) 
{
	int loopok;
    int i;
    int start;
	struct macro *macro;
	struct macro_line *macro_line;
    struct macro_line **last_macro_line = NULL;
	struct macro_label *macro_label;

	if(pi->pass == PASS_1) {
		if(!name) {
			print_msg(pi, MSGTYPE_ERROR, "missing macro name");
			return(True);
		}
		get_next_token(name, TERM_END);

		for(i = 0; !IS_END_OR_COMMENT(name[i]); i++) {	
			if(!IS_LABEL(name[i])) {
				print_msg(pi, MSGTYPE_ERROR, "illegal characters used in macro name '%s'",name);
				return(False);
			}
		}

		macro = calloc(1, sizeof(struct macro));
		if(!macro) {
			print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
			return(False);
		}

  		if(pi->last_macro)
			pi->last_macro->next = macro;
		else
			pi->first_macro = macro;
		pi->last_macro = macro;
		macro->name = malloc(strlen(name) + 1);
		if(!macro->name) {
			print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
			return(False);
		}
		strcpy(macro->name, name);
		macro->include_file = pi->fi->include_file;
		macro->first_line_number = pi->fi->line_number;
		last_macro_line = &macro->first_macro_line;
	}
	else {  /* pi->pass == PASS_2 */
		if(pi->list_line && pi->list_on) {
			fprintf(pi->list_file, "          %s\n", pi->list_line);
			pi->list_line = NULL;
		}
		// reset macro label running numbers
		get_next_token(name, TERM_END);
		macro = get_macro(pi, name);
		if (!macro) {
			print_msg(pi, MSGTYPE_ERROR, "macro inconsistency in '%s'", name);
			return(True);
		}
		for(macro_label = macro->first_label; macro_label; macro_label = macro_label->next) {
			macro_label->running_number = 0;
		}
	}

	loopok = True;
	while(loopok) {
		if(fgets_new(pi,pi->fi->buff, LINEBUFFER_LENGTH, pi->fi->fp)) {
			pi->fi->line_number++;
			i = 0;
			while(IS_HOR_SPACE(pi->fi->buff[i]) && !IS_END_OR_COMMENT(pi->fi->buff[i])) i++;
			if(pi->fi->buff[i] == '.') {
			  i++;
			  if(!nocase_strncmp(&pi->fi->buff[i], "endm", 4))
				loopok = False;
			  if(!nocase_strncmp(&pi->fi->buff[i], "endmacro", 8))
				loopok = False;
			}
			if(pi->pass == PASS_1) {
				if(loopok) {
					i = 0; /* find start of line */
					while(IS_HOR_SPACE(pi->fi->buff[i]) && !IS_END_OR_COMMENT(pi->fi->buff[i])) {
     					i++;
					}
					start = i;
					/* find end of line */
					while(!IS_END_OR_COMMENT(pi->fi->buff[i]) && (IS_LABEL(pi->fi->buff[i]) || pi->fi->buff[i] == ':')) {
     					i++;
					}
					if(pi->fi->buff[i-1] == ':' && (pi->fi->buff[i-2] == '%' 
     					&& (IS_HOR_SPACE(pi->fi->buff[i]) || IS_END_OR_COMMENT(pi->fi->buff[i])))) {
						if(macro->first_label) {
							for(macro_label = macro->first_label; macro_label->next; macro_label=macro_label->next){}
             				macro_label->next = calloc(1,sizeof(struct macro_label));
             				macro_label = macro_label->next;
		   				}
         				else {
             				macro_label = calloc(1,sizeof(struct macro_label));
             				macro->first_label = macro_label;
                		}
                		macro_label->label = malloc(strlen(&pi->fi->buff[start])+1);
                		pi->fi->buff[i-1] = '\0';
           				strcpy(macro_label->label, &pi->fi->buff[start]);
                		pi->fi->buff[i-1] = ':';
           				macro_label->running_number = 0;
					}
				
					macro_line = calloc(1, sizeof(struct macro_line));
					if(!macro_line) {
						print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
						return(False);
					}
					*last_macro_line = macro_line;
					last_macro_line = &macro_line->next;
					macro_line->line = malloc(strlen(pi->fi->buff) + 1);
					if(!macro_line->line) {
						print_msg(pi, MSGTYPE_OUT_OF_MEM, NULL);
						return(False);
					}
					strcpy(macro_line->line, &pi->fi->buff[start]);
				}
			}
			else if(pi->fi->buff && pi->list_file && pi->list_on) {
				if(pi->fi->buff[i] == ';')
					fprintf(pi->list_file, "         %s\n", pi->fi->buff);
				else
					fprintf(pi->list_file, "          %s\n", pi->fi->buff);
			}
		}
		else {
			if(feof(pi->fi->fp)) {
				print_msg(pi, MSGTYPE_ERROR, "Found no closing .ENDMACRO");
				return(True);
			}
			else {
				perror(pi->fi->include_file->name);
				return(False);
			}
		}
	}
	return(True);
}