📄 parse.c
字号:
free(res); } if (freeCmd) { free(args[2]); } } else { /* * Normal assignment -- just do it. */ Var_Set (line, cp, ctxt); }}/*- * ParseAddCmd -- * Lst_ForEach function to add a command line to all targets * * Results: * Always 0 * * Side Effects: * A new element is added to the commands list of the node. */static intParseAddCmd(gn, cmd) GNode *gn; /* the node to which the command is to be added */ char *cmd; /* the command to add */{ /* if target already supplied, ignore commands */ if (!(gn->type & OP_HAS_COMMANDS)) (void)Lst_AtEnd(gn->commands, (ClientData)cmd); return(0);}/*- *----------------------------------------------------------------------- * ParseHasCommands -- * Callback procedure for Parse_File when destroying the list of * targets on the last dependency line. Marks a target as already * having commands if it does, to keep from having shell commands * on multiple dependency lines. * * Results: * Always 0. * * Side Effects: * OP_HAS_COMMANDS may be set for the target. * *----------------------------------------------------------------------- */static intParseHasCommands(gn) GNode *gn; /* Node to examine */{ if (!Lst_IsEmpty(gn->commands)) { gn->type |= OP_HAS_COMMANDS; } return(0);}/*- *----------------------------------------------------------------------- * Parse_AddIncludeDir -- * Add a directory to the path searched for included makefiles * bracketed by double-quotes. Used by functions in main.c * * Results: * None. * * Side Effects: * The directory is appended to the list. * *----------------------------------------------------------------------- */voidParse_AddIncludeDir (dir) char *dir; /* The name of the directory to add */{ Dir_AddDir (parseIncPath, dir);}/*- *--------------------------------------------------------------------- * ParseDoInclude -- * Push to another file. * * The input is the line minus the #include. A file spec is a string * enclosed in <> or "". The former is looked for only in sysIncPath. * The latter in . and the directories specified by -I command line * options * * Results: * None * * Side Effects: * A structure is added to the includes Lst and readProc, lineno, * fname and curFILE are altered for the new file *--------------------------------------------------------------------- */static voidParseDoInclude (file) char *file; /* file specification */{ char *fullname; /* full pathname of file */ IFile *oldFile; /* state associated with current file */ char endc; /* the character which ends the file spec */ char *cp; /* current position in file spec */ Boolean isSystem; /* TRUE if makefile is a system makefile */ /* * Skip to delimiter character so we know where to look */ while ((*file == ' ') || (*file == '\t')) { file++; } if ((*file != '"') && (*file != '<')) { Parse_Error (PARSE_FATAL, ".include filename must be delimited by '\"' or '<'"); return; } /* * Set the search path on which to find the include file based on the * characters which bracket its name. Angle-brackets imply it's * a system Makefile while double-quotes imply it's a user makefile */ if (*file == '<') { isSystem = TRUE; endc = '>'; } else { isSystem = FALSE; endc = '"'; } /* * Skip to matching delimiter */ for (cp = ++file; *cp && *cp != endc; cp++) { continue; } if (*cp != endc) { Parse_Error (PARSE_FATAL, "Unclosed %cinclude filename. '%c' expected", '.', endc); return; } *cp = '\0'; /* * Substitute for any variables in the file name before trying to * find the thing. */ file = Var_Subst (NULL, file, VAR_CMD, FALSE); /* * Now we know the file's name and its search path, we attempt to * find the durn thing. A return of NULL indicates the file don't * exist. */ if (!isSystem) { /* * Include files contained in double-quotes are first searched for * relative to the including file's location. We don't want to * cd there, of course, so we just tack on the old file's * leading path components and call Dir_FindFile to see if * we can locate the beast. */ char *prefEnd; prefEnd = strrchr (fname, '/'); if (prefEnd != (char *)NULL) { char *newName; *prefEnd = '\0'; newName = str_concat (fname, file, STR_ADDSLASH); fullname = Dir_FindFile (newName, parseIncPath); if (fullname == (char *)NULL) { fullname = Dir_FindFile(newName, dirSearchPath); } free (newName); *prefEnd = '/'; } else { fullname = (char *)NULL; } } else { fullname = (char *)NULL; } if (fullname == (char *)NULL) { /* * System makefile or makefile wasn't found in same directory as * included makefile. Search for it first on the -I search path, * then on the .PATH search path, if not found in a -I directory. * XXX: Suffix specific? */ fullname = Dir_FindFile (file, parseIncPath); if (fullname == (char *)NULL) { fullname = Dir_FindFile(file, dirSearchPath); } } if (fullname == (char *)NULL) { /* * Still haven't found the makefile. Look for it on the system * path as a last resort. */ fullname = Dir_FindFile(file, sysIncPath); } if (fullname == (char *) NULL) { *cp = endc; Parse_Error (PARSE_FATAL, "Could not find %s", file); return; } /* * Once we find the absolute path to the file, we get to save all the * state from the current file before we can start reading this * include file. The state is stored in an IFile structure which * is placed on a list with other IFile structures. The list makes * a very nice stack to track how we got here... */ oldFile = (IFile *) emalloc (sizeof (IFile)); oldFile->fname = fname; oldFile->F = curFILE; oldFile->p = curPTR; oldFile->lineno = lineno; (void) Lst_AtFront (includes, (ClientData)oldFile); /* * Once the previous state has been saved, we can get down to reading * the new file. We set up the name of the file to be the absolute * name of the include file so error messages refer to the right * place. Naturally enough, we start reading at line number 0. */ fname = fullname; lineno = 0; curFILE = fopen (fullname, "r"); curPTR = NULL; if (curFILE == (FILE * ) NULL) { Parse_Error (PARSE_FATAL, "Cannot open %s", fullname); /* * Pop to previous file */ (void) ParseEOF(0); }}/*- *--------------------------------------------------------------------- * Parse_FromString -- * Start Parsing from the given string * * Results: * None * * Side Effects: * A structure is added to the includes Lst and readProc, lineno, * fname and curFILE are altered for the new file *--------------------------------------------------------------------- */voidParse_FromString(str) char *str;{ IFile *oldFile; /* state associated with this file */ if (DEBUG(FOR)) (void) fprintf(stderr, "%s\n----\n", str); oldFile = (IFile *) emalloc (sizeof (IFile)); oldFile->lineno = lineno; oldFile->fname = fname; oldFile->F = curFILE; oldFile->p = curPTR; (void) Lst_AtFront (includes, (ClientData)oldFile); curFILE = NULL; curPTR = (PTR *) emalloc (sizeof (PTR)); curPTR->str = curPTR->ptr = str; lineno = 0; fname = strdup(fname);}#ifdef SYSVINCLUDE/*- *--------------------------------------------------------------------- * ParseTraditionalInclude -- * Push to another file. * * The input is the line minus the "include". The file name is * the string following the "include". * * Results: * None * * Side Effects: * A structure is added to the includes Lst and readProc, lineno, * fname and curFILE are altered for the new file *--------------------------------------------------------------------- */static voidParseTraditionalInclude (file) char *file; /* file specification */{ char *fullname; /* full pathname of file */ IFile *oldFile; /* state associated with current file */ char *cp; /* current position in file spec */ char *prefEnd; /* * Skip over whitespace */ while ((*file == ' ') || (*file == '\t')) { file++; } if (*file == '\0') { Parse_Error (PARSE_FATAL, "Filename missing from \"include\""); return; } /* * Skip to end of line or next whitespace */ for (cp = file; *cp && *cp != '\n' && *cp != '\t' && *cp != ' '; cp++) { continue; } *cp = '\0'; /* * Substitute for any variables in the file name before trying to * find the thing. */ file = Var_Subst (NULL, file, VAR_CMD, FALSE); /* * Now we know the file's name, we attempt to find the durn thing. * A return of NULL indicates the file don't exist. * * Include files are first searched for relative to the including * file's location. We don't want to cd there, of course, so we * just tack on the old file's leading path components and call * Dir_FindFile to see if we can locate the beast. * XXX - this *does* search in the current directory, right? */ prefEnd = strrchr (fname, '/'); if (prefEnd != (char *)NULL) { char *newName; *prefEnd = '\0'; newName = str_concat (fname, file, STR_ADDSLASH); fullname = Dir_FindFile (newName, parseIncPath); if (fullname == (char *)NULL) { fullname = Dir_FindFile(newName, dirSearchPath); } free (newName); *prefEnd = '/'; } else { fullname = (char *)NULL; } if (fullname == (char *)NULL) { /* * System makefile or makefile wasn't found in same directory as * included makefile. Search for it first on the -I search path, * then on the .PATH search path, if not found in a -I directory. * XXX: Suffix specific? */ fullname = Dir_FindFile (file, parseIncPath); if (fullname == (char *)NULL) { fullname = Dir_FindFile(file, dirSearchPath); } } if (fullname == (char *)NULL) { /* * Still haven't found the makefile. Look for it on the system * path as a last resort. */ fullname = Dir_FindFile(file, sysIncPath); } if (fullname == (char *) NULL) { Parse_Error (PARSE_FATAL, "Could not find %s", file); return; } /* * Once we find the absolute path to the file, we get to save all the * state from the current file before we can start reading this * include file. The state is stored in an IFile structure which * is placed on a list with other IFile structures. The list makes * a very nice stack to track how we got here... */ oldFile = (IFile *) emalloc (sizeof (IFile)); oldFile->fname = fname; oldFile->F = curFILE; oldFile->p = curPTR; oldFile->lineno = lineno; (void) Lst_AtFront (includes, (ClientData)oldFile); /* * Once the previous state has been saved, we can get down to reading * the new file. We set up the name of the file to be the absolute * name of the include file so error messages refer to the right * place. Naturally enough, we start reading at line number 0. */ fname = fullname; lineno = 0; curFILE = fopen (fullname, "r"); curPTR = NULL; if (curFILE == (FILE * ) NULL) { Parse_Error (PARSE_FATAL, "Cannot open %s", fullname); /* * Pop to previous file */ (void) ParseEOF(1); }}#endif/*- *--------------------------------------------------------------------- * ParseEOF -- * Called when EOF is reached in the current file. If we were reading * an include file, the includes stack is popped and things set up * to go back to reading the previous file at the previous location. * * Results: * CONTINUE if there's more to do. DONE if not. * * Side Effects: * The old curFILE, is closed. The includes list is shortened. * lineno, curFILE, and fname are changed if CONTINUE is returned. *--------------------------------------------------------------------- */static intParseEOF (opened) int opened;{ IFile *ifile; /* the state on the top of the includes stack */ if (Lst_IsEmpty (includes)) { return (DONE); } ifile = (IFile *) Lst_DeQueue (includes); free ((Address) fname); fname = ifile->fname; lineno = ifile->lineno; if (opened && curFILE) (void) fclose (curFILE); if (curPTR) { free((Address) curPTR->str); free((Address) curPTR); } curFILE = ifile->F; curPTR = ifile->p; free ((Address)ifile); return (CONTINUE);}/*- *--------------------------------------------------------------------- * ParseReadc -- * Read a character from the current file * * Results: * The character that was read *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -