722 lines
18 KiB
C
722 lines
18 KiB
C
|
/*-----------------------------------------------------------------------------
|
||
|
xc.c
|
||
|
X Library Compiler
|
||
|
Copyright 2004-2005 Michael Foster (Cross-Browser.com)
|
||
|
Distributed under the terms of the GNU LGPL
|
||
|
|
||
|
v0.28b, 8Aug05, now parses x symbols in quotes. thanks for bug report from Miguel Angel Alvarez
|
||
|
v0.24b, 25May05, removed all doc support for now
|
||
|
-----------------------------------------------------------------------------*/
|
||
|
|
||
|
#include "xc.h"
|
||
|
|
||
|
// Global Variables
|
||
|
|
||
|
struct
|
||
|
{
|
||
|
char name[MAX_NAME_LEN]; // Symbol name, corresponds to an X lib file found in lib_path.
|
||
|
int dep[MAX_SYMBOLS]; /* An array of dependencies for this symbol,
|
||
|
each array element is an index into the symbols array. */
|
||
|
int dep_len; // Length of the dep array.
|
||
|
int inc; /* Indicates the number of times this symbol was found
|
||
|
in the app files. If zero then this X lib file will not
|
||
|
be included in the output js lib file. */
|
||
|
} symbols[MAX_SYMBOLS];
|
||
|
int symbols_len = 0;
|
||
|
|
||
|
struct
|
||
|
{
|
||
|
bool cmp; /* true = Compression applied to output lib js file. Default = true.
|
||
|
Compression removes leading white space, new lines and blank lines.
|
||
|
Also removes "//" comments but does not remove multi-line comments. */
|
||
|
bool lws; // true = Retain leading white space. Default = false.
|
||
|
bool nln; // true = Retain newline chars on non-blank lines. Default = false.
|
||
|
bool bln; // true = Retain blank lines. Default = false.
|
||
|
bool log; // true = Generate log file. Default = false.
|
||
|
bool lib; // true = Generate lib file. Default = true.
|
||
|
bool glb; // true = Include X_GLB_FILE.js. Default = true.
|
||
|
bool dbg; // true = Debug info in log file. Sets options.log to true. Default = false.
|
||
|
bool dep; /* true = Dependents included in output. Default = true.
|
||
|
When false it is useful for creating a lib file from a list of X symbols.
|
||
|
I use -dep to create x_core.js, x_event.js, etc. */
|
||
|
} options;
|
||
|
|
||
|
char x_ver[MAX_NAME_LEN]; // current X version string read from X_VER_FILE
|
||
|
char prj_name[MAX_PATH_LEN]; // The project name (with no extension) must be given on the command line.
|
||
|
char lib_path[MAX_PATH_LEN]; // Path to the X lib files.
|
||
|
char app_files[MAX_APP_FILES][MAX_PATH_LEN]; // Array of app file pathnames.
|
||
|
int app_files_len = 0; // Length of the app_files array.
|
||
|
FILE *log_fp = NULL; // Log file pointer.
|
||
|
|
||
|
// Function Prototypes
|
||
|
|
||
|
int main(int argc, char *argv[]);
|
||
|
bool read_prj_file(char *name);
|
||
|
bool get_x_ver();
|
||
|
bool get_valid_syms();
|
||
|
bool get_lib_file_deps(int sym_idx);
|
||
|
int get_sym_idx(char *symbol);
|
||
|
void set_dep(int sym_idx, int dep);
|
||
|
bool get_app_file_syms(char *fname);
|
||
|
void include_sym(int idx);
|
||
|
bool create_lib();
|
||
|
bool append_lib(FILE *out_fp, char *name);
|
||
|
void skip_ws(char **s);
|
||
|
void rtrim(char *s);
|
||
|
void write_post_log();
|
||
|
|
||
|
// Function Definitions
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
int i;
|
||
|
char log_name[MAX_PATH_LEN];
|
||
|
|
||
|
printf(XC_HDR_STR, XC_VER);
|
||
|
|
||
|
// Read project file.
|
||
|
|
||
|
if (argc <= 1)
|
||
|
{
|
||
|
printf("\nError: No project name specified on command line.\n");
|
||
|
printf(HELP_STR);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
if (!read_prj_file(argv[1])) // Expects argv[1] to be project name with no extension,
|
||
|
{ // and expects to find prjName.PRJ_EXT in current directory.
|
||
|
printf(HELP_STR);
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
// Open log file.
|
||
|
|
||
|
if (options.log)
|
||
|
{
|
||
|
strcpy(log_name, prj_name);
|
||
|
strcat(log_name, LOG_EXT);
|
||
|
if ((log_fp = fopen(log_name, "w")) == NULL)
|
||
|
{
|
||
|
printf("\nWarning: Could not open log file: %s\n", log_name);
|
||
|
}
|
||
|
else if (log_fp) fprintf(log_fp, XC_HDR_STR, XC_VER);
|
||
|
}
|
||
|
|
||
|
get_x_ver(); // Open X_VER_FILE and parse version string
|
||
|
|
||
|
// Create symbol table.
|
||
|
|
||
|
if (!get_valid_syms())
|
||
|
{
|
||
|
if (log_fp)
|
||
|
{
|
||
|
fclose(log_fp);
|
||
|
}
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < symbols_len; ++i)
|
||
|
{
|
||
|
if (!get_lib_file_deps(i))
|
||
|
{
|
||
|
if (log_fp)
|
||
|
{
|
||
|
fclose(log_fp);
|
||
|
}
|
||
|
return 5;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Get symbols from app files.
|
||
|
|
||
|
for (i = 0; i < app_files_len; ++i)
|
||
|
{
|
||
|
if (!get_app_file_syms(app_files[i]))
|
||
|
{
|
||
|
if (log_fp)
|
||
|
{
|
||
|
fclose(log_fp);
|
||
|
}
|
||
|
return 6;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Create output lib.
|
||
|
|
||
|
if (options.lib)
|
||
|
{
|
||
|
if (!create_lib())
|
||
|
{
|
||
|
if (log_fp)
|
||
|
{
|
||
|
fclose(log_fp);
|
||
|
}
|
||
|
return 7;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Report results.
|
||
|
|
||
|
printf("\ncreated ");
|
||
|
if (options.lib) printf("%s%s", prj_name, LIB_EXT);
|
||
|
if (options.lib && log_fp) printf(" and ");
|
||
|
if (log_fp) printf("%s%s", prj_name, LOG_EXT);
|
||
|
printf("\n");
|
||
|
|
||
|
if (log_fp)
|
||
|
{
|
||
|
write_post_log();
|
||
|
fclose(log_fp);
|
||
|
}
|
||
|
|
||
|
return 0; // success
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Reads options, libpath and appfiles from project file.
|
||
|
See the xc_reference for project file details.
|
||
|
*/
|
||
|
bool read_prj_file(char *name)
|
||
|
{
|
||
|
FILE *fp;
|
||
|
bool opt;
|
||
|
char *p, line[MAX_LINE_LEN], *t, token[MAX_PATH_LEN];
|
||
|
|
||
|
strcpy(prj_name, name);
|
||
|
strcpy(line, prj_name); // use 'line' temporarily
|
||
|
strcat(line, PRJ_EXT);
|
||
|
if ((fp = fopen(line, "r")) == NULL)
|
||
|
{
|
||
|
printf("\nError: Could not open project file: %s%s\n", name, PRJ_EXT);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
// option defaults
|
||
|
options.glb = true;
|
||
|
options.dep = true;
|
||
|
options.log = false;
|
||
|
options.lib = true;
|
||
|
options.dbg = false;
|
||
|
options.cmp = true;
|
||
|
options.lws = false;
|
||
|
options.nln = false;
|
||
|
options.bln = false;
|
||
|
|
||
|
while (fgets(line, sizeof(line), fp) != NULL )
|
||
|
{
|
||
|
p = line;
|
||
|
skip_ws(&p);
|
||
|
// skip newlines and comment lines
|
||
|
if (*p == ';' || *p == '\n')
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
// expect directive as first token on line
|
||
|
t = token;
|
||
|
while (*p && *p != ' ' && *p != '\t' && *p != '\n' && *p != ';')
|
||
|
{
|
||
|
*t++ = *p++;
|
||
|
}
|
||
|
*t = 0;
|
||
|
skip_ws(&p);
|
||
|
// process directive
|
||
|
if (!_stricmp(token, "libpath"))
|
||
|
{
|
||
|
t = token;
|
||
|
while (*p && *p != '\n' && *p != ';')
|
||
|
{
|
||
|
*t++ = *p++;
|
||
|
}
|
||
|
*t = 0;
|
||
|
rtrim(token);
|
||
|
strcpy(lib_path, token);
|
||
|
}
|
||
|
else if (!_stricmp(token, "appfiles"))
|
||
|
{
|
||
|
// get app file pathnames (expects one per line)
|
||
|
app_files_len = 0;
|
||
|
while (fgets(line, sizeof(line), fp) != NULL )
|
||
|
{
|
||
|
p = line;
|
||
|
skip_ws(&p);
|
||
|
if (*p != ';' && *p != '\n')
|
||
|
{
|
||
|
rtrim(p);
|
||
|
strcpy(app_files[app_files_len++], p);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
else if (!_stricmp(token, "options"))
|
||
|
{
|
||
|
// parse space-separated options on this line
|
||
|
while (*p && *p != '\n' && *p != ';')
|
||
|
{
|
||
|
t = token;
|
||
|
while (*p && *p != ' ' && *p != '\t' && *p != '\n' && *p != ';')
|
||
|
{
|
||
|
*t++ = *p++;
|
||
|
}
|
||
|
*t = 0;
|
||
|
skip_ws(&p);
|
||
|
opt = *token == '-' ? false : true;
|
||
|
if (strstr(token, "dep")) { options.dep = opt; }
|
||
|
else if (strstr(token, "cmp")) { options.cmp = opt; }
|
||
|
else if (strstr(token, "lws")) { options.lws = opt; }
|
||
|
else if (strstr(token, "bln")) { options.bln = opt; }
|
||
|
else if (strstr(token, "nln")) { options.nln = opt; }
|
||
|
else if (strstr(token, "log")) { options.log = opt; }
|
||
|
else if (strstr(token, "lib")) { options.lib = opt; }
|
||
|
else if (strstr(token, "glb")) { options.glb = opt; }
|
||
|
else if (strstr(token, "dbg")) { options.dbg = opt; }
|
||
|
} // end while
|
||
|
if (options.dbg) { options.log = true; }
|
||
|
}
|
||
|
}
|
||
|
fclose(fp);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Parse X version string from X_VER_FILE.js
|
||
|
*/
|
||
|
bool get_x_ver()
|
||
|
{
|
||
|
int i;
|
||
|
FILE *fp;
|
||
|
char line[MAX_LINE_LEN], *p;
|
||
|
|
||
|
*x_ver = 0;
|
||
|
strcpy(line, lib_path);
|
||
|
strcat(line, X_VER_FILE);
|
||
|
strcat(line, LIB_EXT);
|
||
|
if ((fp = fopen(line, "r")) == NULL)
|
||
|
{
|
||
|
printf("\nWarning: Could not find X version file: %s%s%s\n", lib_path, X_VER_FILE, LIB_EXT);
|
||
|
if (log_fp) fprintf(log_fp, "\nWarning: Could not find X version file: %s%s%s\n", lib_path, X_VER_FILE, LIB_EXT);
|
||
|
return false;
|
||
|
}
|
||
|
while (fgets(line, sizeof(line), fp) != NULL)
|
||
|
{
|
||
|
i = 0;
|
||
|
p = strchr(line, '\"');
|
||
|
if (p)
|
||
|
{
|
||
|
++p;
|
||
|
while (*p && *p != '\"')
|
||
|
{
|
||
|
x_ver[i++] = *p++;
|
||
|
}
|
||
|
x_ver[i] = 0;
|
||
|
}
|
||
|
}
|
||
|
if (!*x_ver)
|
||
|
{
|
||
|
printf("\nWarning: Could not read X version from file: %s%s%s\n", lib_path, X_VER_FILE, LIB_EXT);
|
||
|
if (log_fp) fprintf(log_fp, "\nWarning: Could not read X version from file: %s%s%s\n", lib_path, X_VER_FILE, LIB_EXT);
|
||
|
return false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
printf("\ncompiling %s from X %s ...\n", prj_name, x_ver);
|
||
|
if (log_fp) fprintf(log_fp, "\ncompiling %s from X %s ...\n", prj_name, x_ver);
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
All filenames, minus extensions, in the libpath directory
|
||
|
which match LIB_FILE_MASK constitute the set of valid X symbols.
|
||
|
*/
|
||
|
bool get_valid_syms()
|
||
|
{
|
||
|
int i;
|
||
|
long hFile;
|
||
|
bool status = false;
|
||
|
struct _finddata_t fd;
|
||
|
char dir[MAX_PATH_LEN];
|
||
|
char *p;
|
||
|
|
||
|
strcpy(dir, lib_path);
|
||
|
strcat(dir, LIB_FILE_MASK);
|
||
|
if ((hFile = _findfirst(dir, &fd)) == -1L)
|
||
|
{
|
||
|
printf("\nError: Could not find %s%s\n", lib_path, LIB_FILE_MASK);
|
||
|
if (log_fp) fprintf(log_fp,"\nError: Could not find %s%s\n", lib_path, LIB_FILE_MASK);
|
||
|
status = false;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
do
|
||
|
{
|
||
|
strcpy(symbols[symbols_len].name, fd.name);
|
||
|
p = strchr(symbols[symbols_len].name, '.');
|
||
|
if (p) *p = 0; // remove '.js' extension
|
||
|
symbols[symbols_len].dep_len = 0;
|
||
|
for (i = 0; i < MAX_SYMBOLS; ++i)
|
||
|
{
|
||
|
symbols[symbols_len].dep[i] = INVALID;
|
||
|
}
|
||
|
++symbols_len;
|
||
|
} while (_findnext(hFile, &fd) == 0);
|
||
|
_findclose(hFile);
|
||
|
status = true;
|
||
|
}
|
||
|
return status;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Update symbol table with dependency info from the X lib file symbols[sym_idx].
|
||
|
Excludes symbols found in "//" comments.
|
||
|
*/
|
||
|
bool get_lib_file_deps(int sym_idx)
|
||
|
{
|
||
|
int ln = 0;
|
||
|
FILE *fp;
|
||
|
char line[MAX_LINE_LEN], *p, *del = " \n\t,.;:{}()[]=<>?!+-*/%~^|&";
|
||
|
int dep;
|
||
|
|
||
|
strcpy(line, lib_path);
|
||
|
strcat(line, symbols[sym_idx].name);
|
||
|
strcat(line, LIB_EXT);
|
||
|
if ((fp = fopen(line, "r")) == NULL)
|
||
|
{
|
||
|
printf("\nError: Could not find library file: %s%s%s\n", lib_path, symbols[sym_idx].name, LIB_EXT);
|
||
|
if (log_fp) fprintf(log_fp, "\nError: Could not find library file: %s%s%s\n", lib_path, symbols[sym_idx].name, LIB_EXT);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (options.dbg && log_fp) fprintf(log_fp, "\nX Symbols found in lib file %s:\n", line);
|
||
|
|
||
|
while (fgets(line, sizeof(line), fp) != NULL )
|
||
|
{
|
||
|
++ln; // line number
|
||
|
p = strstr(line, "//");
|
||
|
if (p)
|
||
|
{
|
||
|
*p = 0;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
p = line;
|
||
|
}
|
||
|
// skip_ws(&p);
|
||
|
// if (*p && *p != '\n' && (*p != '/' || *(p+1) != '/'))
|
||
|
|
||
|
if (*p && *p != '\n')
|
||
|
{
|
||
|
p = strtok(line, del);
|
||
|
while(p != NULL)
|
||
|
{
|
||
|
if (*p == 'x')
|
||
|
{
|
||
|
dep = get_sym_idx(p);
|
||
|
if (options.dbg && log_fp) fprintf(log_fp, "%s(%i), ", p, dep);
|
||
|
if (options.dep && dep != INVALID && dep != sym_idx)
|
||
|
{
|
||
|
set_dep(sym_idx, dep);
|
||
|
}
|
||
|
}
|
||
|
p = strtok(NULL, del);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
fclose(fp);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Determine if symbol has a valid entry in the symbol table.
|
||
|
*/
|
||
|
int get_sym_idx(char *symbol)
|
||
|
{
|
||
|
int i;
|
||
|
int idx = INVALID;
|
||
|
|
||
|
for (i = 0; i < symbols_len; ++i)
|
||
|
{
|
||
|
if (!_stricmp(symbol, symbols[i].name))
|
||
|
{
|
||
|
idx = i;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return idx;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
if the 'symbols[sym_idx].dep' array does not already contain 'dep'
|
||
|
then assign 'dep' to the next available array element.
|
||
|
*/
|
||
|
void set_dep(int sym_idx, int dep)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
for (i = 0; i < symbols[sym_idx].dep_len; ++i)
|
||
|
{
|
||
|
if (symbols[sym_idx].dep[i] == dep)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
symbols[sym_idx].dep[symbols[sym_idx].dep_len++] = dep;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Determine which X lib files get included in the output library
|
||
|
by searching fname for X symbols.
|
||
|
*/
|
||
|
bool get_app_file_syms(char *fname)
|
||
|
{
|
||
|
int ln = 0;
|
||
|
FILE *fp;
|
||
|
char line[MAX_LINE_LEN], *p, *del = " \n\t,.;:{}()[]=<>?!+-*/%~^|&'\"";
|
||
|
int sym_idx;
|
||
|
|
||
|
if ((fp = fopen(fname, "r")) == NULL)
|
||
|
{
|
||
|
printf("\nError: Could not find application file: %s\n", fname);
|
||
|
if (log_fp) fprintf(log_fp, "\nError: Could not find application file: %s\n", fname);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
if (options.dbg && log_fp) fprintf(log_fp, "\nX Symbols found in app file %s:\n", fname);
|
||
|
while (fgets(line, sizeof(line), fp) != NULL )
|
||
|
{
|
||
|
++ln; // app line number
|
||
|
if (line[0] != '\n')
|
||
|
{
|
||
|
p = strtok(line, del);
|
||
|
while(p != NULL)
|
||
|
{
|
||
|
if (p[0] == 'x')
|
||
|
{
|
||
|
sym_idx = get_sym_idx(p);
|
||
|
if (options.dbg && log_fp) fprintf(log_fp, "%s(%i), ", p, sym_idx);
|
||
|
if (sym_idx != INVALID)
|
||
|
{
|
||
|
include_sym(sym_idx);
|
||
|
}
|
||
|
}
|
||
|
p = strtok(NULL, del);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
fclose(fp);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Indicate the X lib file symbols[sym_idx] (and all it's dependents)
|
||
|
to be included in the output library file.
|
||
|
*/
|
||
|
void include_sym(int sym_idx)
|
||
|
{
|
||
|
int i;
|
||
|
|
||
|
if (!symbols[sym_idx].inc++)
|
||
|
{
|
||
|
for (i = 0; i < symbols[sym_idx].dep_len; ++i)
|
||
|
{
|
||
|
include_sym(symbols[sym_idx].dep[i]);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Create the output library file.
|
||
|
For every symbol which has 'symbols[sym_idx].inc == true'
|
||
|
include the corresponding X lib file in the output lib.
|
||
|
*/
|
||
|
bool create_lib()
|
||
|
{
|
||
|
int sym_idx;
|
||
|
FILE *out_fp;
|
||
|
char out_file[MAX_PATH_LEN];
|
||
|
|
||
|
strcpy(out_file, prj_name);
|
||
|
strcat(out_file, LIB_EXT);
|
||
|
if ((out_fp = fopen(out_file, "w")) == NULL)
|
||
|
{
|
||
|
printf("\nError: Could not create output lib file: %s%s\n", prj_name, LIB_EXT);
|
||
|
if (log_fp) fprintf(log_fp, "\nError: Could not create output lib file: %s%s\n", prj_name, LIB_EXT);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
fprintf(out_fp, X_HDR_STR, out_file, x_ver, XC_VER);
|
||
|
if (options.glb)
|
||
|
{
|
||
|
if (!append_lib(out_fp, X_GLB_FILE))
|
||
|
{
|
||
|
printf("\nWarning: Could not add %s%s to output\n", X_GLB_FILE, LIB_EXT);
|
||
|
if (log_fp) fprintf(log_fp, "\nWarning: Could not add %s%s to output\n", X_GLB_FILE, LIB_EXT);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
for (sym_idx = 0; sym_idx < symbols_len; ++sym_idx)
|
||
|
{
|
||
|
if (symbols[sym_idx].inc)
|
||
|
{
|
||
|
if (!append_lib(out_fp, symbols[sym_idx].name))
|
||
|
{
|
||
|
printf("\nWarning: Could not add %s%s to output\n", symbols[sym_idx].name, LIB_EXT);
|
||
|
if (log_fp) fprintf(log_fp, "\nWarning: Could not add %s%s to output\n", symbols[sym_idx].name, LIB_EXT);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
fclose(out_fp);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Appends name to the output library js file.
|
||
|
Optionally applies compression, which does not
|
||
|
remove multi-line comments nor sequential white-space.
|
||
|
*/
|
||
|
bool append_lib(FILE *out_fp, char *name)
|
||
|
{
|
||
|
int i;
|
||
|
FILE *lib_fp;
|
||
|
char lib_name[MAX_PATH_LEN];
|
||
|
char *p, line[MAX_LINE_LEN], buf[MAX_LINE_LEN];
|
||
|
|
||
|
strcpy(lib_name, lib_path);
|
||
|
strcat(lib_name, name);
|
||
|
strcat(lib_name, LIB_EXT);
|
||
|
if ((lib_fp = fopen(lib_name, "r")) == NULL)
|
||
|
{
|
||
|
printf("\nError: Could not find library file: %s\n", lib_name);
|
||
|
if (log_fp) fprintf(log_fp, "\nError: Could not find library file: %s\n", lib_name);
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
while (fgets(line, sizeof(line), lib_fp) != NULL )
|
||
|
{
|
||
|
if (!options.cmp)
|
||
|
{
|
||
|
if (fputs(line, out_fp) == EOF)
|
||
|
{
|
||
|
fclose(lib_fp);
|
||
|
printf("\nError: Could not write to output library file: %s%s\n", prj_name, LIB_EXT);
|
||
|
if (log_fp) fprintf(log_fp, "\nError: Could not write to library file: %s%s\n", prj_name, LIB_EXT);
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
p = line;
|
||
|
if (!options.lws) // skip leading whitespace
|
||
|
{
|
||
|
while (*p && (*p == ' ' || *p == '\t'))
|
||
|
{
|
||
|
++p;
|
||
|
}
|
||
|
}
|
||
|
if (!options.bln && (!*p || *p == '\n')) // skip blank lines
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
if (*p)
|
||
|
{
|
||
|
// eat chars and skip newlines and skip from "//" thru rest of line
|
||
|
i = 0;
|
||
|
while (*p && (*p != '\n' || options.nln) && (*p != '/' || *(p+1) != '/'))
|
||
|
{
|
||
|
buf[i++] = *p++;
|
||
|
}
|
||
|
buf[i] = 0;
|
||
|
// write to output file
|
||
|
if (fputs(buf, out_fp) == EOF)
|
||
|
{
|
||
|
fclose(lib_fp);
|
||
|
printf("\nError: Could not write to output library file: %s%s\n", prj_name, LIB_EXT);
|
||
|
if (log_fp) fprintf(log_fp, "\nError: Could not write to output library file: %s%s\n", prj_name, LIB_EXT);
|
||
|
return false;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
fclose(lib_fp);
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Increment *s past all white-space.
|
||
|
*/
|
||
|
void skip_ws(char **s)
|
||
|
{
|
||
|
while (**s == ' ' || **s == '\t')
|
||
|
{
|
||
|
++*s;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Remove whitespace and newlines from end of s
|
||
|
*/
|
||
|
void rtrim(char *s)
|
||
|
{
|
||
|
char *p;
|
||
|
|
||
|
p = s + (strlen(s) - 1);
|
||
|
while (*p == ' ' || *p == '\t' || *p == '\n')
|
||
|
{
|
||
|
--p;
|
||
|
}
|
||
|
++p;
|
||
|
*p = 0;
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
Write project info, app file list and symbol table to the log file.
|
||
|
*/
|
||
|
void write_post_log()
|
||
|
{
|
||
|
int i, j;
|
||
|
|
||
|
fprintf(log_fp, "\nProject Info:\n\n");
|
||
|
fprintf(log_fp, "project file: %s%s\n", prj_name, PRJ_EXT);
|
||
|
fprintf(log_fp, "output lib file: %s%s\n", prj_name, LIB_EXT);
|
||
|
fprintf(log_fp, "library path: %s\n", lib_path);
|
||
|
fprintf(log_fp, "options: cmp=%i, lws=%i, nln=%i, bln=%i, log=%i, lib=%i, glb=%i, dbg=%i, dep=%i\n",
|
||
|
options.cmp,
|
||
|
options.lws,
|
||
|
options.nln,
|
||
|
options.bln,
|
||
|
options.log,
|
||
|
options.lib,
|
||
|
options.glb,
|
||
|
options.dbg,
|
||
|
options.dep);
|
||
|
|
||
|
fprintf(log_fp, "\nApplication Files:\n\n");
|
||
|
for (i = 0; i < app_files_len; ++i)
|
||
|
{
|
||
|
fprintf(log_fp, "%i: %s\n", i, app_files[i]);
|
||
|
}
|
||
|
|
||
|
fprintf(log_fp, "\nOutput Files:\n\n");
|
||
|
if (options.lib) fprintf(log_fp, " %s%s", prj_name, LIB_EXT);
|
||
|
if (log_fp) fprintf(log_fp, ", %s%s", prj_name, LOG_EXT);
|
||
|
fprintf(log_fp, "\n");
|
||
|
|
||
|
fprintf(log_fp, "\nSymbol Table:\n\n");
|
||
|
for (i = 0; i < symbols_len; ++i)
|
||
|
{
|
||
|
fprintf(log_fp, "%i: %s, %i", i, symbols[i].name, symbols[i].inc);
|
||
|
for (j = 0; j < symbols[i].dep_len; ++j)
|
||
|
{
|
||
|
if (options.dbg)
|
||
|
{ // by number
|
||
|
fprintf(log_fp, ", %i", symbols[i].dep[j]);
|
||
|
}
|
||
|
else
|
||
|
{ // by name
|
||
|
fprintf(log_fp, ", %s", symbols[symbols[i].dep[j]].name);
|
||
|
}
|
||
|
}
|
||
|
fprintf(log_fp, "\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// end xc.c
|