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]); }
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); }
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 = ¯o->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 = ¯o_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); }