void SplitAddAttr (Collection* C, const char* Combined, const char* Name) /* Split a combined name/value pair and add it as an attribute to C. Some * attributes may not need a name. If the name is missing, use Name. If * Name is NULL, terminate with an error. */ { /* Name and value are separated by an equal sign */ const char* Pos = strchr (Combined, '='); if (Pos == 0) { /* Combined is actually a value */ if (Name == 0) { Error ("Command line attribute `%s' doesn't contain a name", Combined); } AddAttr (C, Name, Combined); } else { /* Must split name and value */ StrBuf N = AUTO_STRBUF_INITIALIZER; SB_CopyBuf (&N, Combined, Pos - Combined); SB_Terminate (&N); /* Add the attribute */ AddAttr (C, SB_GetConstBuf (&N), Pos+1); /* Release memory */ SB_Done (&N); } }
static AFile* NewAFile (IFile* IF, FILE* F) /* Create a new AFile, push it onto the stack, add the path of the file to * the path search list, and finally return a pointer to the new AFile struct. */ { StrBuf Path = AUTO_STRBUF_INITIALIZER; /* Allocate a AFile structure */ AFile* AF = (AFile*) xmalloc (sizeof (AFile)); /* Initialize the fields */ AF->Line = 0; AF->F = F; AF->Input = IF; /* Increment the usage counter of the corresponding IFile. If this * is the first use, set the file data and output debug info if * requested. */ if (IF->Usage++ == 0) { /* Get file size and modification time. There a race condition here, * since we cannot use fileno() (non standard identifier in standard * header file), and therefore not fstat. When using stat with the * file name, there's a risk that the file was deleted and recreated * while it was open. Since mtime and size are only used to check * if a file has changed in the debugger, we will ignore this problem * here. */ struct stat Buf; if (FileStat (IF->Name, &Buf) != 0) { /* Error */ Fatal ("Cannot stat `%s': %s", IF->Name, strerror (errno)); } IF->Size = (unsigned long) Buf.st_size; IF->MTime = (unsigned long) Buf.st_mtime; /* Set the debug data */ g_fileinfo (IF->Name, IF->Size, IF->MTime); } /* Insert the new structure into the AFile collection */ CollAppend (&AFiles, AF); /* Get the path of this file and add it as an extra search path. * To avoid file search overhead, we will add one path only once. * This is checked by the PushSearchPath function. */ SB_CopyBuf (&Path, IF->Name, FindName (IF->Name) - IF->Name); SB_Terminate (&Path); AF->SearchPath = PushSearchPath (UsrIncSearchPath, SB_GetConstBuf (&Path)); SB_Done (&Path); /* Return the new struct */ return AF; }
int NewInputFile (const char* Name) /* Open a new input file. Returns true if the file could be successfully opened ** and false otherwise. */ { int RetCode = 0; /* Return code. Assume an error. */ char* PathName = 0; FILE* F; struct stat Buf; StrBuf NameBuf; /* No need to initialize */ StrBuf Path = AUTO_STRBUF_INITIALIZER; unsigned FileIdx; CharSource* S; /* If this is the main file, just try to open it. If it's an include file, ** search for it using the include path list. */ if (FCount == 0) { /* Main file */ F = fopen (Name, "r"); if (F == 0) { Fatal ("Cannot open input file '%s': %s", Name, strerror (errno)); } } else { /* We are on include level. Search for the file in the include ** directories. */ PathName = SearchFile (IncSearchPath, Name); if (PathName == 0 || (F = fopen (PathName, "r")) == 0) { /* Not found or cannot open, print an error and bail out */ Error ("Cannot open include file '%s': %s", Name, strerror (errno)); goto ExitPoint; } /* Use the path name from now on */ Name = PathName; } /* Stat the file and remember the values. There's a race condition here, ** since we cannot use fileno() (non-standard identifier in standard ** header file), and therefore not fstat. When using stat with the ** file name, there's a risk that the file was deleted and recreated ** while it was open. Since mtime and size are only used to check ** if a file has changed in the debugger, we will ignore this problem ** here. */ if (FileStat (Name, &Buf) != 0) { Fatal ("Cannot stat input file '%s': %s", Name, strerror (errno)); } /* Add the file to the input file table and remember the index */ FileIdx = AddFile (SB_InitFromString (&NameBuf, Name), (FCount == 0)? FT_MAIN : FT_INCLUDE, Buf.st_size, (unsigned long) Buf.st_mtime); /* Create a new input source variable and initialize it */ S = xmalloc (sizeof (*S)); S->Func = &IFFunc; S->V.File.F = F; S->V.File.Pos.Line = 0; S->V.File.Pos.Col = 0; S->V.File.Pos.Name = FileIdx; SB_Init (&S->V.File.Line); /* Push the path for this file onto the include search lists */ SB_CopyBuf (&Path, Name, FindName (Name) - Name); SB_Terminate (&Path); S->V.File.IncSearchPath = PushSearchPath (IncSearchPath, SB_GetConstBuf (&Path)); S->V.File.BinSearchPath = PushSearchPath (BinSearchPath, SB_GetConstBuf (&Path)); SB_Done (&Path); /* Count active input files */ ++FCount; /* Use this input source */ UseCharSource (S); /* File successfully opened */ RetCode = 1; ExitPoint: /* Free an allocated name buffer */ xfree (PathName); /* Return the success code */ return RetCode; }