mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-15 22:02:51 -06:00
+UppBuilder: upp file parser and makefile generator
git-svn-id: svn://ultimatepp.org/upp/trunk@4562 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
c3c2ffc1be
commit
8f918d4f6d
18 changed files with 1753 additions and 0 deletions
251
uppbox/UppBuilder/Make.hpp
Normal file
251
uppbox/UppBuilder/Make.hpp
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
#include <time.h>
|
||||
|
||||
String ParseCustomStep(const String& s){
|
||||
String cmd;
|
||||
for(const char* c=~s;*c;c++){
|
||||
if(c[0]=='\\' && c[1]=='\"') continue;
|
||||
if(strncmp(c,"$(PATH)",7)==0){
|
||||
cmd+="$$f";
|
||||
c+=6;
|
||||
} else if(strncmp(c,"$(DIR)",6)==0){
|
||||
cmd+="`dirname $$f`";
|
||||
c+=5;
|
||||
} else if(strncmp(c,"$(FILE)",7)==0){
|
||||
cmd+="`basename $$f`";
|
||||
c+=6;
|
||||
} else if(strncmp(c,"$(TITLE)",8)==0){
|
||||
cmd+="`basename $$f | sed 's/[.][^.]*$//'`";
|
||||
c+=7;
|
||||
} else if(strncmp(c,"$(OUTDIR)",9)==0){
|
||||
cmd+="$(BIN)/";
|
||||
c+=8;
|
||||
} else
|
||||
cmd+=*c;
|
||||
// $(INCLUDE),$(!) etc. not implemented yet
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
|
||||
String CustomRule(String rule, const String& pkg){
|
||||
String ext=ReadValue(rule);
|
||||
String cmd=ParseCustomStep(ReadValue(rule));
|
||||
//ignore last part for simplicity
|
||||
if (cmd.IsEmpty() || ext.IsEmpty())
|
||||
return "";
|
||||
if (ext=="pre-link")
|
||||
return " $E cd $("+pkg+"_src) &&"
|
||||
"echo \" Applying custom build pre-link step "
|
||||
"(warning: this is an experimental feature)\"; "
|
||||
+cmd+";\n";
|
||||
if (ext=="post-link")
|
||||
return " $E cd $("+pkg+"_src) &&"
|
||||
"echo \" Applying custom build post-link step "
|
||||
"(warning: this is an experimental feature)\"; "
|
||||
+cmd+";\n";
|
||||
return " $E cd $("+pkg+"_src) && for f in *"+ext+"; "
|
||||
"do echo \" Applying custom build step on $$f "
|
||||
"(warning: this is an experimental feature)\"; "
|
||||
+cmd+"; done;\n";
|
||||
}
|
||||
|
||||
void Parser::Process(){
|
||||
String uppout=GetEnv("OUT","/tmp/_out");
|
||||
String makefile=uppout+"/Makefile";
|
||||
FILE* mf=fopen(makefile,"w");
|
||||
if(!mf){
|
||||
printf("Failed to open file %s\n", ~makefile);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(mf, "# This is an automatically generated makefile for %s package\n"
|
||||
"# You should never need to modify it...\n", ~main);
|
||||
|
||||
bool dep = GetEnv("DEPS","0")=="1";
|
||||
bool color = GetEnv("COLOR","0")=="1";
|
||||
String includes;
|
||||
Vector<String> inc;
|
||||
Split(GetEnv("INCPATHS"),inc);
|
||||
for(int i=0; i<nests.GetCount(); i++)
|
||||
includes+=" -I"+nests[i];
|
||||
for(int i=0; i<inc.GetCount(); i++)
|
||||
includes+=" -I"+inc[i];
|
||||
|
||||
String libpaths;
|
||||
Vector<String> lpaths;
|
||||
Split(GetEnv("LIBPATHS"),lpaths);
|
||||
for(int i=0; i<lpaths.GetCount(); i++)
|
||||
libpaths+=" -L"+lpaths[i];
|
||||
|
||||
time_t rawtime;
|
||||
time(&rawtime);
|
||||
char date[90];
|
||||
struct tm* t = localtime(&rawtime);
|
||||
sprintf(date," -DbmYEAR=%i -DbmMONTH=%i -DbmDAY=%i -DbmHOUR=%i -DbmMINUTE=%i -DbmSECOND=%i",
|
||||
t->tm_year+1900, t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
|
||||
|
||||
fprintf(mf, "OUT:=%s\n"
|
||||
"BIN:=%s\n"
|
||||
"CFLAGS:=%s\n"
|
||||
"CXXFLAGS:=%s\n"
|
||||
"SPEEDFLAGS:=%s\n"
|
||||
"SIZEFLAGS:=%s\n"
|
||||
"LDFLAGS:=%s\n"
|
||||
"CC:=%s\n"
|
||||
"CXX:=%s\n"
|
||||
"AR:=%s\n"
|
||||
"MKDIRP:=%s\n"
|
||||
"E:=%s\n"
|
||||
"M:=%s\n"
|
||||
"C:=%s\n"
|
||||
"B:=%s\n"
|
||||
"N:=%s\n"
|
||||
"mc=$M \" Compiling $C$<$N\"\n"
|
||||
"ma=$M \"=> $BCreating archive$N $C$@$N\"\n"
|
||||
"cc=$E $(CC) -c -x c %s $< -o $@ $(CPPFLAGS) %s\n"
|
||||
"cxx=$E $(CXX) -c -x c++ %s $< -o $@ $(CPPFLAGS) %s\n"
|
||||
"includes:=%s\n"
|
||||
"LIBPATHS:=%s\n"
|
||||
"default: build\n"
|
||||
".PHONY:build clean createdirs custom default\n\n",
|
||||
~uppout, ~GetEnv("BIN","$(OUT)/bin"),
|
||||
~GetEnv("CFLAGS","-O2"),
|
||||
~GetEnv("CXXFLAGS","$(CFLAGS)"),
|
||||
~GetEnv("SPEEDFLAGS","-O3 -ffunction-sections -fdata-sections"),
|
||||
~GetEnv("SIZEFLAGS","-Os -finline-limit=20 -ffunction-sections -fdata-sections"),
|
||||
~GetEnv("LDFLAGS","-Wl,--gc-sections -Wl,-s -Wl,-O,2"),
|
||||
~GetEnv("CC","$(CC)"), ~GetEnv("CXX","$(CXX)"),
|
||||
~GetEnv("AR","ar -src"), ~GetEnv("MKDIRP","mkdir -p"),
|
||||
GetEnv("ECHO","0")=="1"?"":"@",
|
||||
GetEnv("SILENT","0")=="1"?"@true":(color?"@echo -e":"@echo"),
|
||||
color?(const char*)("\\e[3"+GetEnv("HIGHLIGHT","4")+"m"):"",
|
||||
color?"\\e[1m":"", color?"\\e[0m":"",
|
||||
dep?"-MMD":"", date, dep?"-MMD":"",
|
||||
date, ~includes, ~libpaths);
|
||||
String icpps, archives, prelink, postlink, custom;
|
||||
Vector<String> dirs;
|
||||
dirs.Add("$(BIN)");
|
||||
for(int i=0;i<pkgs.GetCount();i++){
|
||||
const String& pkg=pkgs[i].name;
|
||||
String base=BaseName(pkg);
|
||||
String objlist;
|
||||
Vector<String> pflags;
|
||||
|
||||
String opt;
|
||||
//we add the internal includes twice, to fix the case with relative paths... isn't there a better solution?
|
||||
opt=EvalVector(pkgs[i].include,i,"-I");
|
||||
opt+=EvalVector(pkgs[i].include,i,"-I$("+pkg+"_src)/");
|
||||
opt+=EvalVector(pkgs[i].option,i,"");
|
||||
for(int j=0;j<pkgs[i].flags.GetCount();j++)
|
||||
opt+=" -Dflag"+pkgs[i].flags[j];
|
||||
|
||||
String fdir=pkg+"/"+FlagDir(pkgs[i].flags);
|
||||
fprintf(mf, "%s", ~(pkg+"_src="+pkgs[i].dir+"\n"+
|
||||
pkg+"_out=$(OUT)/"+fdir+"\n"+
|
||||
pkg+"_opt=$(includes) "+opt+"\n"));
|
||||
for(int j=0; j<pkgs[i].files.GetCount(); j++){
|
||||
const File& f=pkgs[i].files[j];
|
||||
dirs.AddUnique(DirName("$("+pkg+"_out)/"+f.name));
|
||||
if(f.lang == "brc"){
|
||||
fprintf(mf, "$(%s_out)/%s.o: $(%s_src)/%s\n"
|
||||
" $(mc)\n"
|
||||
" $E sh $(OUT)/brc.sh $< > $(%s_out)/%s.cpp\n"
|
||||
" $E $(CXX) -c -x c++ $(%s_out)/%s.cpp -o $@ $(CPPFLAGS) $(CXXFLAGS)\n",
|
||||
~pkg, ~f.name, ~pkg, ~f.name, ~pkg, ~f.name, ~pkg, ~f.name);
|
||||
objlist+=" $("+pkg+"_out)/"+f.name+".o";
|
||||
continue;
|
||||
}
|
||||
String ext,fopt;
|
||||
if(f.lang=="c++")
|
||||
opt="$(CXXFLAGS) ";
|
||||
else if(f.lang=="c")
|
||||
opt="$(CFLAGS) ";
|
||||
if(pkgs[i].opt==SPEED) ext=".speed.o";
|
||||
else if(pkgs[i].opt==SIZE) ext=".size.o";
|
||||
else{
|
||||
if(f.opt==SPEED) ext=".speed.o";
|
||||
if(f.opt==SIZE) ext=".size.o";
|
||||
else ext=".o";
|
||||
}
|
||||
if(ext==".speed.o")
|
||||
fopt+="$(SPEEDFLAGS)";
|
||||
else if(ext==".size.o")
|
||||
fopt+="$(SIZEFLAGS)";
|
||||
String fn="$("+pkg+"_out)/" + f.name + ext;
|
||||
if(dep){
|
||||
String dep = uppout + "/" + fdir + "/" + f.name + ext;
|
||||
dep[dep.GetCount()-1]='d';
|
||||
dep=LoadFile(dep);
|
||||
if(dep.GetCount())
|
||||
fprintf(mf, "%s", ~dep);
|
||||
else
|
||||
fprintf(mf, "%s: $("+pkg+"_src)/%s\n", ~fn, ~f.name);
|
||||
} else {
|
||||
fprintf(mf, "%s: $("+pkg+"_src)/%s\n", ~fn, ~f.name);
|
||||
}
|
||||
fprintf(mf," $(mc)\n"
|
||||
" $(%s) %s $(%s_opt)\n",
|
||||
~f.lang, ~fopt, ~pkg);
|
||||
|
||||
if(f.name.Mid(f.name.GetCount()-4)=="icpp")
|
||||
icpps+=" "+fn;
|
||||
else
|
||||
objlist+=" "+fn;
|
||||
}
|
||||
fprintf(mf,"%s_custom:\n", ~pkgs[i].name);
|
||||
for(int j=0;j<pkgs[i].custom.GetCount();j++){
|
||||
if(EvalOpt(pkgs[i].custom[j],i)){
|
||||
if(pkgs[i].custom[j].item.Compare("\"pre-link\"",10)==0)
|
||||
prelink+=CustomRule(pkgs[i].custom[j].item, pkgs[i].name);
|
||||
else if(pkgs[i].custom[j].item.Compare("\"post-link\"",11)==0)
|
||||
postlink+=CustomRule(pkgs[i].custom[j].item, pkgs[i].name);
|
||||
else{
|
||||
String rule = CustomRule(pkgs[i].custom[j].item, pkgs[i].name);
|
||||
if(rule=="") continue;
|
||||
fprintf(mf,"%s",~rule);
|
||||
custom+=" "+pkgs[i].name+"_custom";
|
||||
}
|
||||
}
|
||||
}
|
||||
fprintf(mf,"$(%s_out)/%s.a:%s\n"
|
||||
" $(ma)\n"
|
||||
" $E $(AR) $@ $^\n\n",
|
||||
~pkg, ~base, ~objlist);
|
||||
archives="$("+pkg+"_out)/"+base+".a "+archives;
|
||||
}
|
||||
String liblist,optlist,dirlist;
|
||||
for(int i=0;i<libs.GetCount();i++)
|
||||
liblist+=" -l"+libs[i];
|
||||
for(int i=0;i<linkopts.GetCount();i++)
|
||||
optlist+=" "+linkopts[i];
|
||||
for(int i=0;i<dirs.GetCount();i++)
|
||||
dirlist+=" "+dirs[i];
|
||||
String target = GetEnv("TARGET");
|
||||
if(target.IsEmpty()){
|
||||
target=BaseName(main);
|
||||
for(int i=0;i<pkgs[0].target.GetCount();i++){
|
||||
if(EvalOpt(pkgs[0].target[i],0)){
|
||||
target = pkgs[0].target[i].item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(target[0]!='/')
|
||||
target="$(BIN)/"+target;
|
||||
dirs.AddUnique(DirName(target));
|
||||
fprintf(mf, "build: createdirs %s %s\n", ~custom, ~target);
|
||||
fprintf(mf, "%s: %s %s\n"
|
||||
" $M \"$BLinking$N $C$@$N\"\n"
|
||||
" $E $(CXX) -o $@ $(LDFLAGS) $(LIBPATHS) %s -Wl,--start-group $^ %s -Wl,--end-group\n"
|
||||
"%s",
|
||||
/*~prelink,*/ ~target, ~icpps, ~archives, ~optlist, ~liblist, ~postlink);
|
||||
fprintf(mf, "createdirs:\n"
|
||||
" $M \" $BCreating necessary directories ...$N\"\n"
|
||||
" $E mkdir -p%s\n",
|
||||
~dirlist);
|
||||
String clean;
|
||||
for(int i=0;i<pkgs.GetCount();i++)
|
||||
clean+=" $("+pkgs[i].name+"_out)";
|
||||
fprintf(mf,"clean:\n"
|
||||
" $E rm -rf %s",~clean);
|
||||
fclose(mf);
|
||||
}
|
||||
213
uppbox/UppBuilder/Makefile.in
Normal file
213
uppbox/UppBuilder/Makefile.in
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
########################################################################
|
||||
# __ __ _ _ __ __ __ _ _ ___ ___ __ __ ___ #
|
||||
# ( )( ) _( )_ _( )_ ( \/ ) ( ) ( )/ )( _)( _)( )( ) ( _) #
|
||||
# )(__)( (_ _)(_ _) ) ( /__\ ) \ ) _) ) _) )( )(__ ) _) #
|
||||
# \____/ (_) (_) (_/\/\_)(_)(_)(_)\_)(___)(_) (__)(____)(___) #
|
||||
# #
|
||||
############################## USAGE ###################################
|
||||
# This makefile is controlled through a set of variables, similar to #
|
||||
# any other makefile. The prefered way to change them is via command #
|
||||
# line, e.g.: make PKG="ide usvn" CXX=g++ #
|
||||
# #
|
||||
# All of the variables that can control the bahaviour are listed below #
|
||||
# in DEFAULTS section. Also their default value is shown here. Notice #
|
||||
# that many of them can contain shell commands (enclosed in ``) which #
|
||||
# are evaluated before parsing and building each package.
|
||||
# #
|
||||
# For boolean type of variables value "1" represents true, anything #
|
||||
# else is evaluated as false. #
|
||||
############################# TARGETS ##################################
|
||||
# This makefile defines five targets that are meant to be used #
|
||||
# directly by user from the command line: #
|
||||
# #
|
||||
# all - builds all (default if any packages are specified) #
|
||||
# help - shows this help (default if no packages are given) #
|
||||
# simulate - prints all commands, without executing them #
|
||||
# clean - deletes all compiled files related to given packages #
|
||||
# dist-clean - deletes the entire OUT directory (including parsers) #
|
||||
############################# EXAMPLES #################################
|
||||
# Typical usage: #
|
||||
# make PKG=ide FLAGS="GCC" #
|
||||
# More complicated usage: #
|
||||
# make PKG="ide UWord Bombs" FLAGS="GCC .NOGTK" ECHO=1 #
|
||||
# Show help: #
|
||||
# make help #
|
||||
# Silent mode: #
|
||||
# make PKG=ide SILENT=1 #
|
||||
############################# DEFAULTS #################################
|
||||
# List of packages to build (space separated). If empty, this help #
|
||||
# text will be shown. #
|
||||
PKG:=
|
||||
# Paths where to look for packages. #
|
||||
NESTS:=uppsrc bazaar examples reference tutorial $$HOME/MyApps
|
||||
# Building flags (as in TheIDE).
|
||||
FLAGS:=GCC
|
||||
# Additional include paths for compiler (without the leading "-I"). #
|
||||
INCPATHS:= /usr/include/freetype2 /usr/include/gtk-2.0
|
||||
INCPATHS+= /usr/local/include/gtk-2.0 /usr/include/glib-2.0
|
||||
INCPATHS+= /usr/local/include/glib-2.0 /usr/lib/glib-2.0/include
|
||||
INCPATHS+= /usr/local/lib/glib-2.0/include /usr/lib/gtk-2.0/include
|
||||
INCPATHS+= /usr/local/lib/gtk-2.0/include /usr/include/cairo
|
||||
INCPATHS+= /usr/include/pango-1.0 /usr/include/atk-1.0
|
||||
INCPATHS+= /usr/X11R6/include /usr/X11R6/include/freetype2
|
||||
INCPATHS+= /usr/X11R6/include/gtk-2.0 /usr/X11R6/include/glib-2.0
|
||||
INCPATHS+= /usr/X11R6/lib/glib-2.0/include
|
||||
INCPATHS+= /usr/X11R6/lib/gtk-2.0/include /usr/X11R6/include/cairo
|
||||
INCPATHS+= /usr/X11R6/include/pango-1.0 /usr/X11R6/include/atk-1.0
|
||||
INCPATHS+= /usr/local/include/cairo /usr/local/include/pango-1.0
|
||||
INCPATHS+= /usr/local/include/atk-1.0 /usr/local/include
|
||||
INCPATHS+= /usr/local/include/libpng /usr/include/gdk-pixbuf-2.0
|
||||
INCPATHS+= /usr/lib/i386-linux-gnu/glib-2.0/include
|
||||
INCPATHS+= /usr/lib/x86_64-linux-gnu/glib-2.0/include
|
||||
# Paths to libraries for linker. #
|
||||
LIBPATHS:=/usr/X11R6/lib /usr/lib /usr/local/lib
|
||||
# Directory to store intermediate object files #
|
||||
OUT:=_out
|
||||
# Directory where the resulting binaries will be stored #
|
||||
BIN:=$(OUT)/bin
|
||||
# ar command #
|
||||
AR:=ar -src
|
||||
# Command to create directories equivalent to "mkdir -p". The only #
|
||||
# good reason to change is if your platform uses mkdir command which #
|
||||
# doesn't support the -p option #
|
||||
MKDIRP:=mkdir -p
|
||||
# C compiler command #
|
||||
CC:=cc
|
||||
# C++ compiler command #
|
||||
CXX:=c++
|
||||
# Options for C/C++ preprocessor #
|
||||
CPPFLAGS:=
|
||||
# Options for C compiler #
|
||||
CFLAGS:=
|
||||
# Options for C++ compiler #
|
||||
CXXFLAGS:=
|
||||
# Options for linker #
|
||||
LDFLAGS:=-Wl,--gc-sections -Wl,-s -Wl,-O,2
|
||||
# Additional options for speed optimization #
|
||||
SPEEDFLAGS:=-O3 -ffunction-sections -fdata-sections
|
||||
# Additional options for size optimization #
|
||||
SIZEFLAGS:=-Os -finline-limit=20 -ffunction-sections -fdata-sections
|
||||
# Optimization, supply SPEED or SIZE to optimize the executables #
|
||||
OPT:=
|
||||
# Platform flag, added to FLAGS, can include shell commands #
|
||||
PLATFORM:=`uname | tr a-z A-Z` POSIX
|
||||
# Suppress all messagges #
|
||||
SILENT:=0
|
||||
# Print each executed command #
|
||||
ECHO:=0
|
||||
# Use dependency files. This will probably work only with gcc-like #
|
||||
# compilers (requires -MD option). The build usually works correctly #
|
||||
# even without specifying the dependencies unless you modify included #
|
||||
# files (*.h, *.lay, ...) without modifying the *.c/cpp files that #
|
||||
# include them. #
|
||||
DEPS:=0
|
||||
# Run the executable(s) sequntially when compiled #
|
||||
RUN:=0
|
||||
# Override default name of final executable (absolute or relative path)
|
||||
TARGET:=
|
||||
# Add flags from based on mainconfig section (1-based index, set #
|
||||
# to 0 to disable completely #
|
||||
USEMAINCFG:=1
|
||||
# Ask for some additional details during parsing #
|
||||
INTERACTIVE:=0
|
||||
# Use colorized output, recognized values are 0, 1 or auto #
|
||||
COLOR:=auto
|
||||
# What color should be used in colorized mode, number from 0 to 7 #
|
||||
HIGHLIGHT:=4
|
||||
TIME:=TIMEFORMAT=" time taken: %Es"; time
|
||||
########################################################################
|
||||
|
||||
m:=[ "$(SILENT)" = "1" ] || echo
|
||||
e:=@ #comment out for debugging
|
||||
dbgparser:=-DflagDEBUG -ggdb3
|
||||
|
||||
thisfile:=$(MAKEFILE_LIST)$(.MAKEFILE_LIST)
|
||||
color:=if [ "$(COLOR)" = "auto" ]; then [ -t 1 ] && c=1 || c=0; else c="$(COLOR)"; fi
|
||||
pass:=$(color); UPP_NESTS="$(NESTS)" UPP_FLAGS="$(FLAGS)" \
|
||||
UPP_INCPATHS="$(INCPATHS)" UPP_LIBPATHS="$(LIBPATHS)" UPP_OUT="$(OUT)" \
|
||||
UPP_BIN="$(BIN)" UPP_AR="$(AR)" UPP_MKDIRP="$(MKDIRP)" UPP_CC="$(CC)" \
|
||||
UPP_CXX="$(CXX)" UPP_CFLAGS="$(CFLAGS)" UPP_CXXFLAGS="$(CXXFLAGS)" \
|
||||
UPP_LDFLAGS="$(LDFLAGS)" UPP_SPEEDFLAGS="$(SPEEDFLAGS)" \
|
||||
UPP_SIZEFLAGS="$(SIZEFLAGS)" UPP_PLATFORM="$(PLATFORM)" \
|
||||
UPP_SILENT="$(SILENT)" UPP_ECHO="$(ECHO)" UPP_DEPS="$(DEPS)" \
|
||||
UPP_RUN="$(RUN)" UPP_TARGET="$(TARGET)" UPP_USEMAINCFG="$(USEMAINCFG)" \
|
||||
UPP_OPT="$(OPT)" UPP_INTERACTIVE="$(INTERACTIVE)" UPP_COLOR="$$c" \
|
||||
UPP_HIGHLIGHT="$(HIGHLIGHT)"
|
||||
|
||||
all: no-package-specified build
|
||||
|
||||
do-build: $(OUT)/parser $(OUT)/brc.sh $(OUT)/color.sh
|
||||
+$e set -e; $(color); B=""; N=""; C=""; color=""; \
|
||||
[ $$c -eq 1 ] && color="$(SHELL) $(OUT)/color.sh" && B="\e[1m" && N="\e[0m" && C="\e[1;3$(HIGHLIGHT)m"; \
|
||||
for pkg in $(PKG) ; do \
|
||||
$m $${B}Parsing package $$C$$pkg$$N $$B...$$N; \
|
||||
$(TIME) $(pass) $$color $(OUT)/parser $$pkg; \
|
||||
$m $${B}Building package$$N $$C$$pkg$$N $$B...$$N; \
|
||||
$(TIME) $$color $(MAKE) -j 3 -f $(OUT)/Makefile && \
|
||||
$m $${B}Package$$N $$C$$pkg$$N$$B finished ...$$N; \
|
||||
done; set +e
|
||||
|
||||
no-package-specified:
|
||||
$e if [ -z "$(PKG)" ]; then sed '/^$$/{s/.*//;q;}' $(thisfile) && false; fi
|
||||
|
||||
$(OUT)/parser: $(OUT)/parser.cpp
|
||||
@$m Compiling parser...
|
||||
+$e $(TIME) $(CXX) -x c++ -o $@ $^ $(dbgparser)
|
||||
|
||||
$(OUT)/parser.cpp: $(thisfile)
|
||||
@$m "Extracting parser..."
|
||||
+$e [ -d $(OUT) ] || $(MKDIRP) $(OUT)
|
||||
+$e $(TIME) sed -n 's/^#://p;' $< | base64 -d | gzip -d > $@
|
||||
|
||||
$(OUT)/brc.sh: $(thisfile)
|
||||
@$m "Extracting brc parser..."
|
||||
+$e [ -d $(OUT) ] || $(MKDIRP) $(OUT)
|
||||
+$e $(TIME) sed -n 's/^#~//p;' $< | base64 -d | gzip -d > $@
|
||||
|
||||
$(OUT)/color.sh: $(thisfile)
|
||||
@$m "Extracting colorizer script..."
|
||||
+$e [ -d $(OUT) ] || $(MKDIRP) $(OUT)
|
||||
+$e $(TIME) sed -n 's/^#%//p;' $< | base64 -d | gzip -d > $@
|
||||
|
||||
build: do-build
|
||||
$e for pkg in $(PKG); do \
|
||||
if [ "$(RUN)" = "1" ]; then \
|
||||
for target in "$(TARGET)" "$(BIN)/$(TARGET)" "$(BIN)/$$pkg"; do \
|
||||
[ -f "$$target" ] && break; \
|
||||
done; \
|
||||
[ -e "$$target" ] && { $m "Running $$target"; } && $$target; \
|
||||
fi; \
|
||||
done
|
||||
|
||||
simulate: $(OUT)/Makefile
|
||||
+$e for pkg in $(PKG) ; do \
|
||||
$m Parsing package $$pkg ... && \
|
||||
$(pass) $(OUT)/parser $$pkg && \
|
||||
$m Building package $$pkg ... && \
|
||||
$(MAKE) -nf $(OUT)/Makefile; \
|
||||
done
|
||||
|
||||
help:
|
||||
$e sed '/^$$/{s/.*//;q;}' $(thisfile);
|
||||
|
||||
clean:
|
||||
+$e for pkg in $(PKG); do \
|
||||
$m Parsing package $$pkg... && \
|
||||
$(pass) $(OUT)/parser $$pkg && \
|
||||
$m Cleaning package $$pkg && \
|
||||
$(MAKE) -f $(OUT)/Makefile clean; \
|
||||
done
|
||||
|
||||
dist-clean:
|
||||
@$m Deleting $(OUT) ...
|
||||
$e rm -rf $(OUT)
|
||||
|
||||
parser-clean:
|
||||
@$m Deleting parser files ...
|
||||
$e rm -f $(OUT)/parser $(OUT)/parser.cpp
|
||||
|
||||
.SUFFIXES:
|
||||
|
||||
.PHONY: all help simulate clean dist-clean parser-clean \
|
||||
build do-build no-package-specified
|
||||
|
||||
638
uppbox/UppBuilder/Parser.cpp
Normal file
638
uppbox/UppBuilder/Parser.cpp
Normal file
|
|
@ -0,0 +1,638 @@
|
|||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <new>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
template<class T>
|
||||
inline void NEVER(T s){
|
||||
if(s){
|
||||
fprintf(stderr,"ERROR: Something that should never happened has happened...\n");
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
class Vector{
|
||||
int size,alloc;
|
||||
T* p;
|
||||
public:
|
||||
Vector():size(0), alloc(0), p(0) {Resize(2);}
|
||||
~Vector() {Resize(0);}
|
||||
inline int GetCount()const {return size;}
|
||||
inline T& operator[](int n) {return p[n];}
|
||||
inline const T& operator[](int n) const {return p[n];}
|
||||
T& Add(){
|
||||
if(size>=alloc)
|
||||
Resize(2*alloc);
|
||||
return *(new(p+size++) T);
|
||||
}
|
||||
T& Add(const T& x) { return Add()=x; }
|
||||
T& AddUnique(const T& v){
|
||||
int pos=Find(v);
|
||||
if(pos>=0) return p[pos];
|
||||
return Add(v);
|
||||
}
|
||||
int Find(const T& v) const{
|
||||
for(int i=0;i<size;i++){
|
||||
if(v==p[i]) return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
void Resize(int len){
|
||||
if(size>len){
|
||||
for(int i=len;i<size;i++)
|
||||
(p+i)->~T();
|
||||
size=len;
|
||||
}
|
||||
p = (T*)realloc(p,len*sizeof(T));
|
||||
alloc=len;
|
||||
}
|
||||
private:
|
||||
Vector<T>& operator=(const Vector<T>& v){}
|
||||
};
|
||||
|
||||
class String {
|
||||
char* p;
|
||||
public:
|
||||
String() : p(strdup("")) {}
|
||||
String(const String& s) : p(strdup(s.p)){}
|
||||
String(const char* s) : p(strdup(s)) {}
|
||||
~String() {free(p);}
|
||||
|
||||
char& operator[](const int n) const {return p[n];}
|
||||
bool IsEmpty() const {return *p == 0;}
|
||||
const char* operator~() const {return p;}
|
||||
operator const char*() const {return p;}
|
||||
String& operator=(const String& s) {return operator=(s.p);}
|
||||
bool operator==(const char* s) const {return !strcmp(p, s);}
|
||||
bool operator==(const String& s) const {return !strcmp(p, s.p);}
|
||||
void Clear() {free(p); p = strdup("");}
|
||||
int GetCount() const {return strlen(p);}
|
||||
String& operator+=(const String& s){
|
||||
const int lenp = strlen(p);
|
||||
const int lens = strlen(s.p) + 1;
|
||||
p = static_cast<char*>(realloc(p, lenp + lens));
|
||||
NEVER(!p);
|
||||
memmove(p+lenp, s.p, lens);
|
||||
return *this;
|
||||
}
|
||||
String& operator+=(char s){
|
||||
const int lenp = strlen(p);
|
||||
p = static_cast<char*>(realloc(p, lenp + 2));
|
||||
NEVER(!p);
|
||||
p[lenp] = s;
|
||||
p[lenp+1] = 0;
|
||||
return *this;
|
||||
}
|
||||
String& operator=(const char* s){
|
||||
if (p != s) {
|
||||
char *copy = strdup(s);
|
||||
free(p);
|
||||
p = copy;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
int Compare(const char* s, int len=-1) const {
|
||||
return len?strncmp(p,s,len):strcmp(p,s);
|
||||
}
|
||||
int FindLast(const char c) const {
|
||||
for(int i=strlen(p)-1;i>=0;i--)
|
||||
if(p[i]==c) return i;
|
||||
return -1;
|
||||
}
|
||||
int Find(const char* s) const {
|
||||
int lens=strlen(s);
|
||||
int lenp=strlen(p);
|
||||
for(int i=0;i<lenp-lens;i++)
|
||||
if(strncmp(p+i,s,lens)) return i;
|
||||
return -1;
|
||||
}
|
||||
String Mid(const int start, const int length=-1) const{
|
||||
int len = strlen(p)-start;
|
||||
if(len<0){
|
||||
fprintf(stderr, "Error: Invalid parameters to Mid!");
|
||||
exit(1);
|
||||
};
|
||||
if (start+len>length && length>0)
|
||||
len = length;
|
||||
|
||||
String s;
|
||||
free(s.p);
|
||||
s.p = static_cast<char*>(malloc(len+1));
|
||||
NEVER(!s.p);
|
||||
memcpy(s.p, p + start, len);
|
||||
s.p[len] = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
friend String operator+(const String& lhs, const String& rhs);
|
||||
friend int operator<(const String& lhs, const String& rhs);
|
||||
};
|
||||
inline String operator+(const String& lhs, const String& rhs){
|
||||
return String(lhs) += rhs;
|
||||
}
|
||||
inline int operator<(const String& lhs, const String& rhs){
|
||||
return lhs.Compare(~rhs);
|
||||
}
|
||||
|
||||
String ReadValue(String& s,char delim1 = ',',char delim2 = ','){
|
||||
if(s=="") return "";
|
||||
String r;
|
||||
int skip=0;
|
||||
while((s[skip]==delim1 || s[skip] == delim2 || s[skip]<=32) && s[skip]!=0)
|
||||
skip++;
|
||||
s = s.Mid(skip);
|
||||
bool q=false;
|
||||
if(s[0]=='\"'){
|
||||
s = s.Mid(1);
|
||||
q = true;
|
||||
}
|
||||
const char* c = s;
|
||||
for(; *c; c++){
|
||||
if(*c==delim1 || *c==delim2 || (q && *c=='\"') && c[-1] != '\\') break;
|
||||
if(*c<=(q?0:32)) continue;
|
||||
r += *c;
|
||||
}
|
||||
if(q) c++;
|
||||
s = c;
|
||||
return r;
|
||||
};
|
||||
|
||||
bool Consume(String& s,const char* section){
|
||||
int len=strlen(section);
|
||||
if(s.Compare(section,len)==0){
|
||||
s = s.Mid(len);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
enum Opt{NONE, SPEED, SIZE};
|
||||
enum OptState { UNKNOWN, NO, YES };
|
||||
|
||||
struct File{
|
||||
Opt opt;
|
||||
String name, lang;
|
||||
File():opt(NONE){};
|
||||
};
|
||||
|
||||
bool IsSource(File& f){
|
||||
int pos=f.name.FindLast('.');
|
||||
if(!pos)
|
||||
return false;
|
||||
String ext = f.name.Mid(pos+1);
|
||||
for(int i=0;i<ext.GetCount();i++)
|
||||
ext[i]=tolower(ext[i]);
|
||||
if (ext.Compare("cpp") == 0
|
||||
|| ext.Compare("icpp") == 0
|
||||
|| ext.Compare("cc") == 0
|
||||
|| ext.Compare("cxx") == 0){
|
||||
f.lang="cxx";
|
||||
return true;
|
||||
} else if (ext.Compare("c") == 0){
|
||||
f.lang="cc";
|
||||
return true;
|
||||
} else if (ext.Compare("brc") == 0){
|
||||
f.lang="brc";
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
void Slashes(String& s){
|
||||
for(int i=0; i<s.GetCount(); i++){
|
||||
if(s[i]=='\\') s[i]='/';
|
||||
}
|
||||
};
|
||||
|
||||
struct OptItem{
|
||||
String when;
|
||||
String item;
|
||||
mutable OptState state;
|
||||
OptItem():state(UNKNOWN){};
|
||||
};
|
||||
|
||||
bool LoadOpts(String& s, const char *key, Vector<OptItem>& v) {
|
||||
if(Consume(s,key)) {
|
||||
if(s[0]==' ')
|
||||
s = s.Mid(1);
|
||||
String when;
|
||||
if(s[0]=='('){
|
||||
when=s;
|
||||
int len = 0;
|
||||
int lvl = 0;
|
||||
for(const char* c=when; *c; c++) {
|
||||
len++;
|
||||
if(*c == '(') lvl++;
|
||||
else if(*c == ')'){
|
||||
lvl--;
|
||||
if(lvl == 0) break;
|
||||
}
|
||||
}
|
||||
when = s.Mid(0,len);
|
||||
s = s.Mid(len);
|
||||
}
|
||||
do {
|
||||
OptItem& m=v.Add();
|
||||
m.when = when;
|
||||
m.item = ReadValue(s,',');
|
||||
Slashes(m.item);
|
||||
}while(s[0] == ',');
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
String BaseName(const String& s){
|
||||
int pos=s.FindLast('/');
|
||||
if(!pos)
|
||||
return s;
|
||||
return s.Mid(pos+1);
|
||||
};
|
||||
|
||||
String DirName(const String& s){
|
||||
int pos=s.FindLast('/');
|
||||
if(!pos)
|
||||
return "";
|
||||
return s.Mid(0,pos);
|
||||
};
|
||||
|
||||
inline String LoadFile(const String& fn){
|
||||
String r;
|
||||
char b[1000];
|
||||
FILE* f=fopen(~fn,"r");
|
||||
if(!f) return "";
|
||||
int n=0;
|
||||
while(!feof(f)){
|
||||
n+=fread(b,1,1000,f);
|
||||
r+=b;
|
||||
//this is a hack, correct implementation would not need it
|
||||
r=r.Mid(0,n);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
inline String GetEnv(const char* n,const char* s=""){
|
||||
String p("UPP_");
|
||||
p+=n;
|
||||
const char* r=getenv(p);
|
||||
return r?r:s;
|
||||
};
|
||||
|
||||
struct Upp{
|
||||
String name,description,dir;
|
||||
Opt opt;
|
||||
Vector<OptItem> option, link, library, addflags, target, uses, include, custom;
|
||||
Vector<String> accepts, cfgk, cfgv, flags;
|
||||
Vector<File> files;
|
||||
|
||||
Upp() : opt(NONE){};
|
||||
Upp(const String& package) : name(package), opt(NONE){};
|
||||
Upp(const String& package,const Vector<String>& nests)
|
||||
: opt(NONE) {Load(package,nests);}
|
||||
bool operator==(const Upp& u)const {return name==u.name;}
|
||||
Upp& operator=(const Upp& u){NEVER(true); return *this;}
|
||||
String GetClause(FILE* f){
|
||||
String r;
|
||||
int l=0;
|
||||
bool q=false;
|
||||
while(1){
|
||||
int c = fgetc(f);
|
||||
if(c==EOF || (!q && c==';')) break;
|
||||
if(c<=32){
|
||||
if(!r.IsEmpty() && r[r.GetCount()-1]!=' ')
|
||||
r += ' ';
|
||||
continue;
|
||||
} else
|
||||
if (c == '\"' && l != '\\') {
|
||||
q=!q;
|
||||
}
|
||||
l = c;
|
||||
r += c;
|
||||
}
|
||||
return r;
|
||||
};
|
||||
Upp& Load(const String& package,const Vector<String>& nests){
|
||||
name=package;
|
||||
char temp[FILENAME_MAX];
|
||||
String cwd = getcwd(temp, FILENAME_MAX);
|
||||
cwd += "/";
|
||||
String fn;
|
||||
FILE* f(NULL);
|
||||
for(int i=0; i<nests.GetCount(); i++){
|
||||
dir = (nests[i][0]=='/'?"":cwd) + nests[i] + "/" + package;
|
||||
fn = dir + "/" + BaseName(package) + ".upp";
|
||||
f = fopen(fn,"r");
|
||||
if(f) break;
|
||||
}
|
||||
if(!f){
|
||||
fprintf(stderr, "Error: Package %s not found!\n", ~package);
|
||||
exit(1);
|
||||
}
|
||||
String s;
|
||||
while(1){
|
||||
s = GetClause(f);
|
||||
if((LoadOpts(s, "options", option) ||
|
||||
LoadOpts(s, "link", link) ||
|
||||
LoadOpts(s, "library", library) ||
|
||||
LoadOpts(s, "flags", addflags) ||
|
||||
LoadOpts(s, "target", target) ||
|
||||
LoadOpts(s, "uses", uses) ||
|
||||
LoadOpts(s, "include", include))){
|
||||
} else
|
||||
if(Consume(s,"description")){
|
||||
int pos=s.Find("\\377");
|
||||
if(pos)
|
||||
s = s.Mid(0,pos) + "\"";
|
||||
} else
|
||||
if(Consume(s,"acceptflags")) {
|
||||
do{
|
||||
accepts.Add(ReadValue(s));
|
||||
}while(s[0] == ',');
|
||||
} else
|
||||
if(Consume(s,"noblitz")){
|
||||
// ignored for now
|
||||
} else
|
||||
if(Consume(s,"mainconfig")) {
|
||||
do {
|
||||
cfgk.Add(ReadValue(s));
|
||||
while(Consume(s," ") || Consume(s,"\""));
|
||||
Consume(s,"=");
|
||||
cfgv.Add(ReadValue(s));
|
||||
while(Consume(s," ") || Consume(s,"\""));
|
||||
}while(s[0] == ',');
|
||||
} else
|
||||
if(Consume(s,"optimize_speed"))
|
||||
opt = SPEED;
|
||||
else
|
||||
if(Consume(s,"optimize_size"))
|
||||
opt = SIZE;
|
||||
else
|
||||
if(Consume(s,"file")){
|
||||
do{
|
||||
File f;
|
||||
f.name = ReadValue(s,' ');
|
||||
bool separator=false;
|
||||
while(*s && s[0]!=','){
|
||||
String str = ReadValue(s,' ');
|
||||
if(Consume(str,"optimize_speed"))
|
||||
f.opt = SPEED;
|
||||
else if(Consume(str,"optimize_size"))
|
||||
f.opt = SIZE;
|
||||
else if(Consume(str,"separator"))
|
||||
separator=true;
|
||||
}
|
||||
if(!separator && IsSource(f)){
|
||||
Slashes(f.name);
|
||||
files.Add(f);
|
||||
}
|
||||
}while(s[0] == ',');
|
||||
} else
|
||||
if(Consume(s,"custom")){
|
||||
if(s[0]==' ')
|
||||
s = s.Mid(1);
|
||||
OptItem& m=custom.Add();
|
||||
int len = 0;
|
||||
if(s[0]=='('){
|
||||
int lvl = 0;
|
||||
for(const char* c=s; *c; c++) {
|
||||
len++;
|
||||
if(*c == '(') lvl++;
|
||||
else if(*c == ')'){
|
||||
lvl--;
|
||||
if(lvl == 0) break;
|
||||
}
|
||||
}
|
||||
m.when = s.Mid(0,len);
|
||||
}
|
||||
m.item = s.Mid(len);
|
||||
} else
|
||||
if(feof(f))
|
||||
break;
|
||||
}
|
||||
fclose(f);
|
||||
return *this;
|
||||
};
|
||||
};
|
||||
|
||||
inline void Split(String s,Vector<String>& v){
|
||||
while(s.GetCount()) v.AddUnique(ReadValue(s,' '));
|
||||
}
|
||||
|
||||
String FlagDir(const Vector<String>& v){
|
||||
Vector<String> r;
|
||||
//simple insertion sort
|
||||
r.Resize(v.GetCount());
|
||||
for(int i=0;i<v.GetCount();i++)
|
||||
r.Add(v[i]);
|
||||
for (int j=1; j<v.GetCount(); ++j) {
|
||||
const char* c = ~v[j];
|
||||
int i=j-1;
|
||||
while(i>=0 && r[i].Compare(c)>0) {
|
||||
r[i+1]=r[i];
|
||||
i--;
|
||||
}
|
||||
r[i+1]=c;
|
||||
}
|
||||
String s=r[0];
|
||||
for(int i=1;i<r.GetCount();i++)
|
||||
s+="."+r[i];
|
||||
return s;
|
||||
}
|
||||
|
||||
class Parser{
|
||||
Vector<Upp> pkgs;
|
||||
String main;
|
||||
public:
|
||||
Vector<String> nests, flags, dflags, libs, linkopts;
|
||||
static inline bool IsId(int c) {
|
||||
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' || (c >= '0' && c <= '9');
|
||||
}
|
||||
bool sMatchFlag(String& s,int pkg){
|
||||
if(Consume(s,"!"))
|
||||
return !sMatchFlag(s,pkg);
|
||||
if(Consume(s,"(")) {
|
||||
bool b = sMatchOr(s,pkg);
|
||||
Consume(s,")");
|
||||
return b;
|
||||
}
|
||||
if(s.IsEmpty())
|
||||
return true;
|
||||
int len=0;
|
||||
while(IsId(s[len]))
|
||||
len++;
|
||||
String id = s.Mid(0,len);
|
||||
s = s.Mid(len);
|
||||
|
||||
if(flags.Find(id)>=0) return true;
|
||||
for(int j=0;j<dflags.GetCount();j++)
|
||||
if((pkg==0||pkgs[pkg].accepts.Find(dflags[j])>=0) && dflags.Find(id)>=0)
|
||||
return true;
|
||||
if(pkg==0&&id=="MAIN") return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sMatchAnd(String& s,int pkg){
|
||||
bool b = sMatchFlag(s,pkg);
|
||||
while( IsId(s[0]) || s[0]=='!' || s[0]=='(' || Consume(s,"&&") || Consume(s,"&"))
|
||||
b = sMatchFlag(s,pkg) && b;
|
||||
return b;
|
||||
}
|
||||
|
||||
bool sMatchOr(String& s,int pkg){
|
||||
bool b = sMatchAnd(s,pkg);
|
||||
while(Consume(s,"||") || Consume(s,"|"))
|
||||
b = sMatchFlag(s,pkg) || b;
|
||||
return b;
|
||||
}
|
||||
|
||||
bool EvalOpt(const OptItem& opt,int pkg){
|
||||
if(opt.state!=UNKNOWN)
|
||||
return opt.state==YES;
|
||||
String s;
|
||||
for(const char* c = opt.when; *c; c++)
|
||||
if(*c > ' ') s += *c;
|
||||
if(s=="()"){
|
||||
opt.state=YES;
|
||||
return true;
|
||||
}
|
||||
bool b = sMatchOr(s,pkg);
|
||||
if(!s.IsEmpty()){
|
||||
fprintf(stderr, "Error: Invalid WHEN string: %s\n",~opt.when);
|
||||
exit(1);
|
||||
}
|
||||
opt.state=b?YES:NO;
|
||||
return b;
|
||||
}
|
||||
void GetDeps(const String& pkg){
|
||||
if(pkgs.Find(Upp(pkg))>=0)
|
||||
return;
|
||||
Upp& added = pkgs.Add().Load(pkg, nests);
|
||||
Vector<String> u;
|
||||
for(int i=0;i<added.uses.GetCount();i++)
|
||||
if(EvalOpt(added.uses[i],pkgs.GetCount()-1))
|
||||
u.Add(added.uses[i].item);
|
||||
for(int i=0;i<u.GetCount();i++)
|
||||
GetDeps(u[i]);
|
||||
}
|
||||
String EvalVector(const Vector<OptItem>& v,int pkg,const String& prefix){
|
||||
String r;
|
||||
for(int i=0;i<v.GetCount();i++){
|
||||
if(EvalOpt(v[i],pkg))
|
||||
r+=" "+prefix+v[i].item;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
void EvalFlags(){
|
||||
String umc = GetEnv("USEMAINCFG","1");
|
||||
int n;
|
||||
sscanf(~umc,"%d",&n);
|
||||
if(pkgs[0].cfgk.GetCount()==0)
|
||||
fprintf(stderr,"Warning: %s doesn't seem to be a main package.\n", ~pkgs[0].name);
|
||||
String p;
|
||||
bool interactive = GetEnv("INTERACTIVE","0")=="1";
|
||||
if (!interactive) {
|
||||
n=n?n-1:-1;
|
||||
} else if(interactive){
|
||||
if (pkgs[0].cfgk.GetCount()){
|
||||
printf("Multiple configurations available, select one\n");
|
||||
int i=0;
|
||||
for(;i<pkgs[0].cfgk.GetCount();i++)
|
||||
printf(" %i) '%s': '%s'\n",i+1,~pkgs[0].cfgk[i],~pkgs[0].cfgv[i]);
|
||||
printf(" *) Custom flags (type in as space separated list)\n");
|
||||
printf("Your selection [%d]:\n",n);
|
||||
} else {
|
||||
printf("Add custom flags (as space separated list) [\"\"]:\n");
|
||||
}
|
||||
fflush(0);
|
||||
char buf[256];
|
||||
fgets(buf, 256, stdin);
|
||||
if (strlen(buf) == 0 || sscanf(buf, "%d", &n)) {
|
||||
n--;
|
||||
} else {
|
||||
p = buf;
|
||||
n = -1;
|
||||
}
|
||||
}
|
||||
if(n >= 0 && n < pkgs[0].cfgk.GetCount())
|
||||
p = pkgs[0].cfgv[n];
|
||||
if(p)
|
||||
Split(p,flags);
|
||||
p="Using flags";
|
||||
for(int i=0; i<flags.GetCount(); i++)
|
||||
p+=" "+flags[i];
|
||||
printf("%s\n",~p);
|
||||
Vector<String> dflags;
|
||||
for(int i=0; i<flags.GetCount(); i++)
|
||||
if(flags[i][0]=='.'){
|
||||
dflags.Add(flags[i].Mid(1));
|
||||
}
|
||||
pkgs[0].flags.Add("MAIN");
|
||||
for(int i=0;i<pkgs.GetCount();i++){
|
||||
for(int j=0;j<dflags.GetCount();j++)
|
||||
if(i==0 || pkgs[i].accepts.Find(dflags[j])>=0)
|
||||
pkgs[i].flags.Add(dflags[j]);
|
||||
for(int j=0;j<pkgs[i].addflags.GetCount();j++)
|
||||
EvalOpt(pkgs[i].addflags[j],i);
|
||||
Vector<String> remflags;
|
||||
for(int j=0;j<pkgs[i].addflags.GetCount();j++){
|
||||
if(EvalOpt(pkgs[i].addflags[j],i))
|
||||
if(pkgs[i].addflags[j].item[0]=='!')
|
||||
Split(pkgs[i].addflags[j].item.Mid(1), remflags);
|
||||
else
|
||||
Split(pkgs[i].addflags[j].item, pkgs[i].flags);
|
||||
}
|
||||
for(int j=0;j<flags.GetCount();j++){
|
||||
if(flags[j][0]=='.' || remflags.Find(flags[j])>=0) continue;
|
||||
pkgs[i].flags.Add(flags[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
void EvalOpts(){
|
||||
String optimize=GetEnv("OPT");
|
||||
for(int i=0;i<pkgs.GetCount();i++){
|
||||
if(pkgs[i].opt==NONE && optimize.GetCount()){
|
||||
if (optimize=="SPEED")
|
||||
pkgs[i].opt=SPEED;
|
||||
else if (optimize=="SIZE")
|
||||
pkgs[i].opt=SIZE;
|
||||
}
|
||||
for(int j=0;j<pkgs[i].library.GetCount();j++){
|
||||
if(EvalOpt(pkgs[i].library[j],i))
|
||||
for(String s=pkgs[i].library[j].item;s.GetCount();){
|
||||
String v=ReadValue(s,' ');
|
||||
if(v=="" || v==" ") break;
|
||||
libs.AddUnique(v);
|
||||
}
|
||||
}
|
||||
for(int j=0;j<pkgs[i].link.GetCount();j++)
|
||||
if(EvalOpt(pkgs[i].link[j],i))
|
||||
linkopts.Add(pkgs[i].link[j].item);
|
||||
}
|
||||
}
|
||||
Parser(const char* mainpkg) : main(mainpkg){
|
||||
Split(GetEnv("NESTS","uppsrc bazaar reference tutorial examples /home/h/MyApps"), nests);
|
||||
Split(GetEnv("FLAGS","GCC GUI"), flags);
|
||||
Split(GetEnv("PLATFORM","POSIX LINUX"), flags);
|
||||
|
||||
GetDeps(main);
|
||||
EvalFlags();
|
||||
EvalOpts();
|
||||
|
||||
Process();
|
||||
}
|
||||
void Process();
|
||||
};
|
||||
|
||||
#include PROCESS
|
||||
|
||||
int main(int argc, const char *argv[]){
|
||||
if(argc != 2){
|
||||
fprintf(stderr, "Usage: %s package\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
Parser r(argv[1]);
|
||||
return 0;
|
||||
}
|
||||
26
uppbox/UppBuilder/Skeleton.hpp
Normal file
26
uppbox/UppBuilder/Skeleton.hpp
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
This is an example file. Anyone can use it as a base for
|
||||
additional parser output formats.
|
||||
*/
|
||||
|
||||
#define DUMP(X) \
|
||||
printf(#X":\n");\
|
||||
for(int q = 0; q < X.GetCount(); q++) \
|
||||
printf(" [%i] = %s\n", q, ~X[q]);
|
||||
|
||||
void Parser::Process(){
|
||||
DUMP(flags);
|
||||
DUMP(nests);
|
||||
printf("packages:\n");
|
||||
for(int i = 0; i < pkgs.GetCount(); i++){
|
||||
printf(" %s\n", ~pkgs[i].name);
|
||||
for(int j = 0; j < pkgs[i].flags.GetCount(); j++){
|
||||
printf("%s%s", j ?", ":" ", ~pkgs[i].flags[j]);
|
||||
}
|
||||
printf("\n");
|
||||
for(int j = 0; j < pkgs[i].custom.GetCount(); j++){
|
||||
printf(" %s%s\n", ~pkgs[i].custom[j].when, ~pkgs[i].custom[j].item);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
30
uppbox/UppBuilder/UppBuilder.upp
Normal file
30
uppbox/UppBuilder/UppBuilder.upp
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
options(MAKE) -DPROCESS="<UppBuilder/Make.hpp>";
|
||||
|
||||
options(TEST) -DPROCESS="<UppBuilder/Skeleton.hpp>";
|
||||
|
||||
file
|
||||
Parser.cpp,
|
||||
Make readonly separator,
|
||||
Make.hpp,
|
||||
update.sh,
|
||||
Makefile.in highlight sh,
|
||||
color.sh,
|
||||
brc.sh,
|
||||
Test readonly separator,
|
||||
Skeleton.hpp,
|
||||
Doc readonly separator,
|
||||
srcdoc.tpp,
|
||||
src.tpp;
|
||||
|
||||
mainconfig
|
||||
"" = "MAKE",
|
||||
"" = "TEST";
|
||||
|
||||
custom() ".hpp",
|
||||
"sh -c \"if [ Parser.cpp -ot $(FILE) ]; then touch Parser.cpp; fi;\"",
|
||||
"PHONY";
|
||||
|
||||
custom(MAKE) ".in",
|
||||
"sh update.sh",
|
||||
"Makefile";
|
||||
|
||||
66
uppbox/UppBuilder/brc.sh
Normal file
66
uppbox/UppBuilder/brc.sh
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
#!/bin/sh
|
||||
# this script converts .brc file into .c file suitable for compilation
|
||||
# usage: brc.sh file.brc > output.c
|
||||
|
||||
set -e
|
||||
cd "`dirname $1`"
|
||||
f="`basename $1`"
|
||||
|
||||
tmp="`mktemp -d brc_XXXXXX`"
|
||||
sed 's/[(),]/ /g;s/\r//' $f > $tmp/preparsed
|
||||
|
||||
toBin() {
|
||||
case $2 in
|
||||
ZIP) obj=$tmp/obj.gz; cat "$1" | gzip -9 > $obj ;;
|
||||
BZ2) obj=$tmp/obj.bz2; cat "$1" | bzip2 -9 > $obj ;;
|
||||
*) obj="$1" ;;
|
||||
esac
|
||||
hexdump -e '"\t" 16/1 "%i, " "\n"' $obj | sed '$s/[ ,]\+$/, 0/g'
|
||||
len="`cat $obj | wc -c`"
|
||||
}
|
||||
|
||||
BINARY() {
|
||||
echo "static char $1_[] = {"
|
||||
toBin "$2" $3
|
||||
echo "};"
|
||||
echo "char *$1 = $1_;"
|
||||
echo "int $1_length = $len;";
|
||||
}
|
||||
|
||||
BINARY_MASK() {
|
||||
c=0
|
||||
for file in $2; do
|
||||
BINARY_ARRAY $1 $c $file $3
|
||||
c=$(( $c + 1 ))
|
||||
files="$files\n\t\"$file\","
|
||||
done
|
||||
echo -e "char *bin_all_files[] = {$files\n};"
|
||||
}
|
||||
|
||||
BINARY_ARRAY() {
|
||||
echo "static char $1_$2[] = {"
|
||||
toBin "$3" $4
|
||||
echo "};"
|
||||
[ -z "`echo $arrays | grep $1`" ] && arrays="$1 $arrays"
|
||||
echo "$1_$2 $len" >> $tmp/len
|
||||
}
|
||||
|
||||
. $tmp/preparsed | tee $tmp/out
|
||||
|
||||
for a in $arrays; do
|
||||
c="`grep -c $a'_[0-9]\+' $tmp/out`"
|
||||
echo "int $a""_count = $c;"
|
||||
echo "int $a""_length[] = {"
|
||||
n=0
|
||||
while [ $n -lt $c ]; do
|
||||
sed -n "/$a""_$n"' /s/.* \([0-9]*\)/\t\1,/p' $tmp/len
|
||||
n=$(( $n + 1 ))
|
||||
done
|
||||
echo "};"
|
||||
|
||||
echo "char *$a[] = { "
|
||||
grep -o $a'_[0-9]\+' $tmp/out | sed 's/^/\t/;s/$/,/;'
|
||||
echo " };"
|
||||
done
|
||||
|
||||
rm -r $tmp
|
||||
14
uppbox/UppBuilder/color.sh
Normal file
14
uppbox/UppBuilder/color.sh
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#!/bin/sh
|
||||
s='s/error:/\x1B[1;31m&\x1B[0m/ig;
|
||||
s/warning:/\x1B[1;35m&\x1B[0m/ig;
|
||||
s/note:/\x1B[1;32m&\x1B[0m/ig;
|
||||
s/info:/\x1B[1;32m&\x1B[0m/ig;'
|
||||
# redirection magic makes the sed command work on stdout
|
||||
# as well as on stderr, without mixing them up
|
||||
f="`mktemp -t status.XXXXXX`"
|
||||
{ { {
|
||||
$@
|
||||
} ; echo $? > $f; } 3>&1 1>&2 2>&3 | sed "$s"; } 3>&1 1>&2 2>&3 | sed "$s"
|
||||
read ret < $f
|
||||
rm -f $f
|
||||
exit $ret
|
||||
3
uppbox/UppBuilder/init
Normal file
3
uppbox/UppBuilder/init
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#ifndef _UppBuilder_icpp_init_stub
|
||||
#define _UppBuilder_icpp_init_stub
|
||||
#endif
|
||||
45
uppbox/UppBuilder/src.tpp/Misc$en-us.tpp
Normal file
45
uppbox/UppBuilder/src.tpp/Misc$en-us.tpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
topic "miscellaneous structs";
|
||||
[ $$0,0#00000000000000000000000000000000:Default]
|
||||
[i448;a25;kKO9; $$1,0#37138531426314131252341829483380:structitem]
|
||||
[l288;2 $$2,0#27521748481378242620020725143825:desc]
|
||||
[0 $$3,0#96390100711032703541132217272105:end]
|
||||
[H6;0 $$4,0#05600065144404261032431302351956:begin]
|
||||
[i448;a25;kKO9;2 $$5,0#37138531426314131252341829483370:codeitem]
|
||||
[{_}
|
||||
[s1;:File`:`:struct: [@(0.0.255) struct]_[* File]&]
|
||||
[s2;%% Class holding information about file that should be compiled.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:File`:`:opt: Opt_[* opt]&]
|
||||
[s2;%% Speed or size optimization flag&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:File`:`:name: [_^String^ String]_[* name]&]
|
||||
[s2;%% Filename, as specified in .upp file&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:File`:`:lang: [_^String^ String]_[* lang]&]
|
||||
[s2;%% Programming language, one of cxx, c, brc, guessed by extension.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s3; &]
|
||||
[s0; &]
|
||||
[s3; &]
|
||||
[s1;:OptItem`:`:struct: [@(0.0.255) struct]_[* OptItem]&]
|
||||
[s2;%% Class holding any information from .upp file that has WHEN
|
||||
clause.&]
|
||||
[s0;%% &]
|
||||
[s4; &]
|
||||
[s5;:OptItem`:`:when: [_^String^ String]_[* when]&]
|
||||
[s2;%% When clause&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:OptItem`:`:item: [_^String^ String]_[* item]&]
|
||||
[s2;%% The value&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:OptItem`:`:state: [@(0.0.255) mutable]_OptState_[* state]&]
|
||||
[s2;%% UNKNOWN if the clause wasn`'t evaluated yet, otherwise YES
|
||||
or NO, depending on the evaluation result.&]
|
||||
[s3; &]
|
||||
[s0;%% ]
|
||||
31
uppbox/UppBuilder/src.tpp/Parser$en-us.tpp
Normal file
31
uppbox/UppBuilder/src.tpp/Parser$en-us.tpp
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
topic "class Parser";
|
||||
[ $$0,0#00000000000000000000000000000000:Default]
|
||||
[i448;a25;kKO9; $$1,0#37138531426314131252341829483380:structitem]
|
||||
[l288;2 $$2,0#27521748481378242620020725143825:desc]
|
||||
[0 $$3,0#96390100711032703541132217272105:end]
|
||||
[H6;0 $$4,0#05600065144404261032431302351956:begin]
|
||||
[i448;a25;kKO9;2 $$5,0#37138531426314131252341829483370:codeitem]
|
||||
[{_}
|
||||
[s1;:Parser`:`:class: [@(0.0.255) class]_[* Parser]&]
|
||||
[s2;%% Main class that does all the work: loads the main package and
|
||||
all its dependencies, evaluates the contents and outputs the
|
||||
results. The output writer is interchangeable to allow generating
|
||||
information to various build systems.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:Parser`:`:Parser`(const char`*`): [* Parser]([@(0.0.255) const]_[@(0.0.255) char`*]_[*@3 m
|
||||
ainpkg])&]
|
||||
[s2;%% Constructor, the parameter [%-*@3 mainpkg] specifies which package
|
||||
should be parsed, everything else is determined from [^topic`:`/`/UppBuilder`/srcdoc`/environment`$en`-us^ e
|
||||
nvironment variables]&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:Parser`:`:Process`(`): [@(0.0.255) void]_[* Process]()&]
|
||||
[s2;%% The output function, called when everything is parsed. It
|
||||
can access all the information gathered in the parsing stage
|
||||
in order to do whatever necessary to build the package. This
|
||||
function is supplied by backend via macro definition, so it can
|
||||
do exactly what the backend needs, e.g. generate makefile or
|
||||
even call the compiler itself. &]
|
||||
[s3; &]
|
||||
[s0;%% ]
|
||||
112
uppbox/UppBuilder/src.tpp/String$en-us.tpp
Normal file
112
uppbox/UppBuilder/src.tpp/String$en-us.tpp
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
topic "class String";
|
||||
[ $$0,0#00000000000000000000000000000000:Default]
|
||||
[i448;a25;kKO9; $$1,0#37138531426314131252341829483380:structitem]
|
||||
[l288;2 $$2,0#27521748481378242620020725143825:desc]
|
||||
[0 $$3,0#96390100711032703541132217272105:end]
|
||||
[H6;0 $$4,0#05600065144404261032431302351956:begin]
|
||||
[i448;a25;kKO9;2 $$5,0#37138531426314131252341829483370:codeitem]
|
||||
[{_}
|
||||
[s1;:String`:`:class: [@(0.0.255) class]_[* String]&]
|
||||
[s2;%% Class implementing a very basic String. The idea behind reimplementing
|
||||
such basic thing is to avoid including a huge portion of U`+`+/STL,
|
||||
which slows down compilation and also add dependencies.&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:String`:`:String`(`): [* String]()&]
|
||||
[s2;%% Default constructor&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:String`:`:String`(const String`&`): [* String]([@(0.0.255) const]_[* String][@(0.0.255) `&
|
||||
]_[*@3 s])&]
|
||||
[s5;:String`:`:String`(const char`*`): [* String]([@(0.0.255) const]_[@(0.0.255) char`*]_[*@3 s
|
||||
])&]
|
||||
[s2;%% Copy constructors&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:String`:`:`~String`(`): [@(0.0.255) `~][* String]()&]
|
||||
[s2;%% Destructor&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:String`:`:operator`[`]`(const int`)const: [@(0.0.255) char`&]_[* operator`[`]]([@(0.0.255) c
|
||||
onst]_[@(0.0.255) int]_[*@3 n])_[@(0.0.255) const]&]
|
||||
[s2;%% Returns [%-*@3 n]th character&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:String`:`:IsEmpty`(`)const: [@(0.0.255) bool]_[* IsEmpty]()_[@(0.0.255) const]&]
|
||||
[s2;%% Returns true if the String is empty&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:String`:`:operator`~`(`)const: [@(0.0.255) const]_[@(0.0.255) char`*]_[* operator`~]()
|
||||
_[@(0.0.255) const]&]
|
||||
[s2;%% Returns pointer to internal char`* representation, similar
|
||||
to std`::string.c`_str()&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:String`:`:operator const char`*`(`)const: [* operator_const_char`*]()_[@(0.0.255) co
|
||||
nst]&]
|
||||
[s2;%% Converts String to const char`*&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:String`:`:operator`=`(const String`&`): [_^String^ String][@(0.0.255) `&]_[* operator`=
|
||||
]([@(0.0.255) const]_[_^String^ String][@(0.0.255) `&]_[*@3 s])&]
|
||||
[s5;:String`:`:operator`=`(const char`*`): [_^String^ String][@(0.0.255) `&]_[* operator`=](
|
||||
[@(0.0.255) const]_[@(0.0.255) char`*]_[*@3 s])&]
|
||||
[s2;%% Assignment operators&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:String`:`:operator`=`=`(const char`*`)const: [@(0.0.255) bool]_[* operator`=`=]([@(0.0.255) c
|
||||
onst]_[@(0.0.255) char`*]_[*@3 s])_[@(0.0.255) const]&]
|
||||
[s5;:String`:`:operator`=`=`(const String`&`)const: [@(0.0.255) bool]_[* operator`=`=]([@(0.0.255) c
|
||||
onst]_[_^String^ String][@(0.0.255) `&]_[*@3 s])_[@(0.0.255) const]&]
|
||||
[s2;%% Compares string with [%-*@3 s].&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:String`:`:Clear`(`): [@(0.0.255) void]_[* Clear]()&]
|
||||
[s2;%% Empties the String&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:String`:`:GetCount`(`)const: [@(0.0.255) int]_[* GetCount]()_[@(0.0.255) const]&]
|
||||
[s2;%% Returns number of characters stored&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:String`:`:operator`+`=`(const String`&`): [_^String^ String][@(0.0.255) `&]_[* operato
|
||||
r`+`=]([@(0.0.255) const]_[_^String^ String][@(0.0.255) `&]_[*@3 s])&]
|
||||
[s5;:String`:`:operator`+`=`(char`): [_^String^ String][@(0.0.255) `&]_[* operator`+`=]([@(0.0.255) c
|
||||
har]_[*@3 s])&]
|
||||
[s2;%% Adds [%-*@3 s] at the end of the String&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:String`:`:Compare`(const char`*`,int`)const: [@(0.0.255) int]_[* Compare]([@(0.0.255) c
|
||||
onst]_[@(0.0.255) char`*]_[*@3 s], [@(0.0.255) int]_[*@3 len][@(0.0.255) `=`-][@3 1])_[@(0.0.255) c
|
||||
onst]&]
|
||||
[s2;%% Compares the string to [%-*@3 s]. If [%-*@3 len] > 0, then only
|
||||
first [%-*@3 len] characters is considered.&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:String`:`:FindLast`(const char`)const: [@(0.0.255) int]_[* FindLast]([@(0.0.255) const
|
||||
]_[@(0.0.255) char]_[*@3 c])_[@(0.0.255) const]&]
|
||||
[s2;%% Find last occurrence of character [%-*@3 c].&]
|
||||
[s4; &]
|
||||
[s5;:String`:`:Find`(const char`*`)const: [@(0.0.255) int]_[* Find]([@(0.0.255) const]_[@(0.0.255) c
|
||||
har`*]_[*@3 s])_[@(0.0.255) const]&]
|
||||
[s2;%% Find first occurrence of string [%-*@3 s].&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:String`:`:Mid`(const int`,const int`)const: [_^String^ String]_[* Mid]([@(0.0.255) con
|
||||
st]_[@(0.0.255) int]_[*@3 start], [@(0.0.255) const]_[@(0.0.255) int]_[*@3 length][@(0.0.255) `=
|
||||
`-][@3 1])_[@(0.0.255) const]&]
|
||||
[s2;%% Returns a substring starting at [%-*@3 start]. If [%-*@3 length]
|
||||
> 0 the returned string si truncated to the [%-*@3 length] characters.&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:operator`+`(const String`&`,const String`&`): [_^String^ String]_[* operator`+]([@(0.0.255) c
|
||||
onst]_[_^String^ String][@(0.0.255) `&]_[*@3 lhs], [@(0.0.255) const]_[_^String^ String][@(0.0.255) `&
|
||||
]_[*@3 rhs])&]
|
||||
[s2;%% Concatenates [%-*@3 lhs] and [%-*@3 rhs].&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:operator`<`(const String`&`,const String`&`): [@(0.0.255) int]_[* operator<]([@(0.0.255) c
|
||||
onst]_[_^String^ String][@(0.0.255) `&]_[*@3 lhs], [@(0.0.255) const]_[_^String^ String][@(0.0.255) `&
|
||||
]_[*@3 rhs])&]
|
||||
[s2;%% Compares [%-*@3 lhs] and [%-*@3 rhs].&]
|
||||
[s0;%% ]
|
||||
19
uppbox/UppBuilder/src.tpp/Upp$en-us.tpp
Normal file
19
uppbox/UppBuilder/src.tpp/Upp$en-us.tpp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
topic "struct Upp";
|
||||
[ $$0,0#00000000000000000000000000000000:Default]
|
||||
[i448;a25;kKO9; $$1,0#37138531426314131252341829483380:structitem]
|
||||
[l288;2 $$2,0#27521748481378242620020725143825:desc]
|
||||
[0 $$3,0#96390100711032703541132217272105:end]
|
||||
[H6;0 $$4,0#05600065144404261032431302351956:begin]
|
||||
[i448;a25;kKO9;2 $$5,0#37138531426314131252341829483370:codeitem]
|
||||
[{_}
|
||||
[s1;:Upp`:`:struct: [@(0.0.255) struct]_[* Upp]&]
|
||||
[s2;%% Struct representing all data found in .upp file&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:Upp`:`:Load`(const String`&`,const Vector`<String`>`&`): [_^Upp^ Upp][@(0.0.255) `&]_
|
||||
[* Load]([@(0.0.255) const]_[_^String^ String][@(0.0.255) `&]_[*@3 package],[@(0.0.255) const
|
||||
]_[_^Vector^ Vector]<[_^String^ String]>`&_[*@3 nests])&]
|
||||
[s2;%% Finds [%-*@3 package] in [%-*@3 nests] and reads all information
|
||||
from its .upp file&]
|
||||
[s3;%% &]
|
||||
[s0;%% ]
|
||||
63
uppbox/UppBuilder/src.tpp/Vector$en-us.tpp
Normal file
63
uppbox/UppBuilder/src.tpp/Vector$en-us.tpp
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
topic "class Vector";
|
||||
[ $$0,0#00000000000000000000000000000000:Default]
|
||||
[i448;a25;kKO9; $$1,0#37138531426314131252341829483380:structitem]
|
||||
[l288;2 $$2,0#27521748481378242620020725143825:desc]
|
||||
[0 $$3,0#96390100711032703541132217272105:end]
|
||||
[H6;0 $$4,0#05600065144404261032431302351956:begin]
|
||||
[i448;a25;kKO9;2 $$5,0#37138531426314131252341829483370:codeitem]
|
||||
[{_}
|
||||
[s1;:noref: [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T]>&]
|
||||
[s1;:Vector`:`:class: [@(0.0.255) class]_[* Vector]&]
|
||||
[s2;%% Class template implementing a very basic Vector container.
|
||||
The idea behind reimplementing such basic thing is to avoid including
|
||||
a huge portion of U`+`+/STL, which slows down compilation and
|
||||
also add dependencies.&]
|
||||
[s4; &]
|
||||
[s5;:Vector`:`:Vector`(`): [* Vector]()&]
|
||||
[s2;%% Default constructor&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:Vector`:`:`~Vector`(`): [@(0.0.255) `~][* Vector]()&]
|
||||
[s2;%% Destructor&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:Vector`:`:GetCount`(`)const: [@(0.0.255) int]_[* GetCount]()[@(0.0.255) const]&]
|
||||
[s2;%% Returns the number of elements stored&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:Vector`:`:operator`[`]`(int`): [*@4 T][@(0.0.255) `&]_[* operator`[`]]([@(0.0.255) int]_
|
||||
[*@3 n])&]
|
||||
[s2;%% Returns reference to element stored at [%-*@3 n]th position&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:Vector`:`:operator`[`]`(int`)const: [@(0.0.255) const]_[*@4 T][@(0.0.255) `&]_[* operato
|
||||
r`[`]]([@(0.0.255) int]_[*@3 n])_[@(0.0.255) const]&]
|
||||
[s2;%% Returns const reference to element stored at [%-*@3 n]th position&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:Vector`:`:Add`(`): [*@4 T][@(0.0.255) `&]_[* Add]()&]
|
||||
[s2;%% Adds default constructed element at the end of the vector&]
|
||||
[s3; &]
|
||||
[s4; &]
|
||||
[s5;:Vector`:`:Add`(const T`&`): [*@4 T][@(0.0.255) `&]_[* Add]([@(0.0.255) const]_[*@4 T][@(0.0.255) `&
|
||||
]_[*@3 x])&]
|
||||
[s2;%% Adds an element copy constructed from [%-*@3 x] at the end of
|
||||
the vector&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:Vector`:`:AddUnique`(const T`&`): [*@4 T][@(0.0.255) `&]_[* AddUnique]([@(0.0.255) const
|
||||
]_[*@4 T][@(0.0.255) `&]_[*@3 v])&]
|
||||
[s2;%% Adds element [%-*@3 v] at the end of the vector if it doesn`'t
|
||||
exist already&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:Vector`:`:Find`(const T`&`)const: [@(0.0.255) int]_[* Find]([@(0.0.255) const]_[*@4 T][@(0.0.255) `&
|
||||
]_[*@3 v])_[@(0.0.255) const]&]
|
||||
[s2;%% Returns position of [%-*@3 v] in the vector, or `-1 if not present&]
|
||||
[s3;%% &]
|
||||
[s4; &]
|
||||
[s5;:Vector`:`:Resize`(int`): [@(0.0.255) void]_[* Resize]([@(0.0.255) int]_[*@3 len])&]
|
||||
[s2;%% Allocates memory for [%-*@3 len] fields. If the vector is longer,
|
||||
it is truncated.&]
|
||||
[s3;%% &]
|
||||
[s0;%% ]
|
||||
53
uppbox/UppBuilder/src.tpp/global$en-us.tpp
Normal file
53
uppbox/UppBuilder/src.tpp/global$en-us.tpp
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
topic "global functions";
|
||||
[ $$0,0#00000000000000000000000000000000:Default]
|
||||
[H6;0 $$1,0#05600065144404261032431302351956:begin]
|
||||
[i448;a25;kKO9;2 $$2,0#37138531426314131252341829483370:codeitem]
|
||||
[l288;2 $$3,0#27521748481378242620020725143825:desc]
|
||||
[0 $$4,0#96390100711032703541132217272105:end]
|
||||
[i448;a25;kKO9; $$5,0#37138531426314131252341829483380:structitem]
|
||||
[{_}
|
||||
[s2;:NEVER`(T`): [@(0.0.255) template]_<[@(0.0.255) class]_[*@4 T]>_[@(0.0.255) void]_[* NEVER](
|
||||
[*@4 T]_[*@3 s])&]
|
||||
[s3;%% Safely terminates the parser when [%-*@3 s] evaluates to true.
|
||||
Used to end the execution in case of nonrecoverable state.&]
|
||||
[s4;%% &]
|
||||
[s1; &]
|
||||
[s2;:Slashes`(String`&`): [@(0.0.255) void]_[* Slashes]([_^String^ String][@(0.0.255) `&]_[*@3 s
|
||||
])&]
|
||||
[s3;%% Converts all backslashes in [%-*@3 s] to forward slashes.&]
|
||||
[s4;%% &]
|
||||
[s1; &]
|
||||
[s2;:BaseName`(const String`&`): [_^String^ String]_[* BaseName]([@(0.0.255) const]_[_^String^ S
|
||||
tring][@(0.0.255) `&]_[*@3 s])&]
|
||||
[s3;%% Returns everything after last `'/`' character in [%-*@3 s].&]
|
||||
[s4;%% &]
|
||||
[s1; &]
|
||||
[s2;:DirName`(const String`&`): [_^String^ String]_[* DirName]([@(0.0.255) const]_[_^String^ S
|
||||
tring][@(0.0.255) `&]_[*@3 s])&]
|
||||
[s3;%% Returns everything before last `'/`' character in [%-*@3 s].&]
|
||||
[s4;%% &]
|
||||
[s1; &]
|
||||
[s2;:LoadFile`(const String`&`): [_^String^ String]_[* LoadFile]([@(0.0.255) const]_[_^String^ S
|
||||
tring][@(0.0.255) `&]_[*@3 fn])&]
|
||||
[s3;%% Loads content of file [%-*@3 fn] into string.&]
|
||||
[s4;%% &]
|
||||
[s1; &]
|
||||
[s2;:GetEnv`(const char`*`,const char`*`): [_^String^ String]_[* GetEnv]([@(0.0.255) const]_
|
||||
[@(0.0.255) char`*]_[*@3 n],[@(0.0.255) const]_[@(0.0.255) char`*]_[*@3 s][@(0.0.255) `=]`"`"
|
||||
)&]
|
||||
[s3;%% Reads environment variable UPP`_[%-*@3 n], if no such variable
|
||||
is found then [%-*@3 s] is returned.&]
|
||||
[s4;%% &]
|
||||
[s1; &]
|
||||
[s2;:Split`(String`,Vector`<String`>`&`): [@(0.0.255) void]_[* Split]([_^String^ String]_[*@3 s
|
||||
],[_^Vector^ Vector]<[_^String^ String]>`&_[*@3 v])&]
|
||||
[s3;%% Splits string [%-*@3 s] at spaces and adds each chunk into vector
|
||||
[%-*@3 v].&]
|
||||
[s4;%% &]
|
||||
[s1; &]
|
||||
[s2;:FlagDir`(const Vector`<String`>`&`): [_^String^ String]_[* FlagDir]([@(0.0.255) const]_
|
||||
[_^Vector^ Vector]<[_^String^ String]>`&_[*@3 v])&]
|
||||
[s3;%% Sorts contents of [%-*@3 v] alphabetically and concatenates
|
||||
it into string with `'.`' as delimiters&]
|
||||
[s4;%% &]
|
||||
[s0;%% ]
|
||||
18
uppbox/UppBuilder/srcdoc.tpp/TODO$en-us.tpp
Normal file
18
uppbox/UppBuilder/srcdoc.tpp/TODO$en-us.tpp
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
topic "TODO list";
|
||||
[ $$0,0#00000000000000000000000000000000:Default]
|
||||
[{_}%EN-US
|
||||
[s0; Parser:&]
|
||||
[s0;i150;O0; Finish custom build steps support&]
|
||||
[s0;i150;O0; Separate parsing from output&]
|
||||
[s0;i150;O0; Pretify (remove useless variables, remove DBGs, ...)&]
|
||||
[s0;i150;O0; Add comments&]
|
||||
[s0;i150;O0; Extend interactive mode&]
|
||||
[s0; &]
|
||||
[s0; Generated makefile:&]
|
||||
[s0;i150;O0; Simplify and shorten&]
|
||||
[s0; &]
|
||||
[s0; Ideas for future:&]
|
||||
[s0;i150;O0; Shell backend `- building without make&]
|
||||
[s0;i150;O0; other common build systems `- cmake, scons, waf, ...&]
|
||||
[s0;i150;O0; BLITZ support&]
|
||||
[s0; ]
|
||||
46
uppbox/UppBuilder/srcdoc.tpp/deps$en-us.tpp
Normal file
46
uppbox/UppBuilder/srcdoc.tpp/deps$en-us.tpp
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
topic "Dependencies";
|
||||
[2 $$0,0#00000000000000000000000000000000:Default]
|
||||
[l288;i1120;a17;O9;~~~.1408;2 $$1,0#10431211400427159095818037425705:param]
|
||||
[a83;*R6 $$2,5#31310162474203024125188417583966:caption]
|
||||
[H4;b83;*4 $$3,5#07864147445237544204411237157677:title]
|
||||
[i288;O9;C2 $$4,6#40027414424643823182269349404212:item]
|
||||
[b42;a42;2 $$5,5#45413000475342174754091244180557:text]
|
||||
[l288;b17;a17;2 $$6,6#27521748481378242620020725143825:desc]
|
||||
[l321;C@5;1 $$7,7#20902679421464641399138805415013:code]
|
||||
[b2503;2 $$8,0#65142375456100023862071332075487:separator]
|
||||
[*@(0.0.255)2 $$9,0#83433469410354161042741608181528:base]
|
||||
[C2 $$10,0#37138531426314131251341829483380:class]
|
||||
[l288;a17;*1 $$11,11#70004532496200323422659154056402:requirement]
|
||||
[i417;b42;a42;O9;~~~.416;2 $$12,12#10566046415157235020018451313112:tparam]
|
||||
[b167;C2 $$13,13#92430459443460461911108080531343:item1]
|
||||
[i288;a42;O9;C2 $$14,14#77422149456609303542238260500223:item2]
|
||||
[*@2$(0.128.128)2 $$15,15#34511555403152284025741354420178:NewsDate]
|
||||
[l321;*C$7;2 $$16,16#03451589433145915344929335295360:result]
|
||||
[l321;b83;a83;*C$7;2 $$17,17#07531550463529505371228428965313:result`-line]
|
||||
[l160;*C+117 $$18,5#88603949442205825958800053222425:package`-title]
|
||||
[2 $$19,0#53580023442335529039900623488521:gap]
|
||||
[C2 $$20,20#70211524482531209251820423858195:class`-nested]
|
||||
[b50;2 $$21,21#03324558446220344731010354752573:Par]
|
||||
[{_}%EN-US
|
||||
[s3; Dependencies&]
|
||||
[s5; &]
|
||||
[s5; The Makefile produced by this package when MAKE flag is specified
|
||||
aims to be as universal as possible, however it still depends
|
||||
on couple programs:&]
|
||||
[s5;i150;O0; make `- should POSIX compatible (see [^http`:`/`/pubs`.opengroup`.org`/onlinepubs`/009695399`/utilities`/make`.html^ h
|
||||
ttp://pubs.opengroup.org/onlinepubs/009695399/utilities/make.html]),
|
||||
GNU make and remake were tested&]
|
||||
[s5;i150;O0; sed `- again POSIX compatible (see [^http`:`/`/pubs`.opengroup`.org`/onlinepubs`/009695399`/utilities`/sed`.html^ h
|
||||
ttp://pubs.opengroup.org/onlinepubs/009695399/utilities/sed.html])&]
|
||||
[s5;i150;O0; gzip&]
|
||||
[s5;i150;O0; base64&]
|
||||
[s5; Additionaly, for projects using BRC files:&]
|
||||
[s5;i150;O0; grep&]
|
||||
[s5;i150;O0; hexdump&]
|
||||
[s5;i150;O0; bzip2 (only for BRC files that contain bzip2 compressed
|
||||
resources)&]
|
||||
[s5;i150;O0; couple standard utilities found on any system: dirname,
|
||||
basename, mktemp and tee&]
|
||||
[s5; &]
|
||||
[s5; ... and of course a compiler (GCC and Clang tested), ar and
|
||||
linker to build the executables]
|
||||
80
uppbox/UppBuilder/srcdoc.tpp/environment$en-us.tpp
Normal file
80
uppbox/UppBuilder/srcdoc.tpp/environment$en-us.tpp
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
topic "Environment variables";
|
||||
[ $$0,0#00000000000000000000000000000000:Default]
|
||||
[{_}%EN-US
|
||||
[s0; The parser is influenced by several environment variables. &]
|
||||
[s0; &]
|
||||
[s0; Parser:&]
|
||||
[ {{2738:1920:5342h1;^ [s0; [* Variable]]
|
||||
:: [s0; [* Default]]
|
||||
:: [s0; [* Meaning]]
|
||||
:: [s0; UPP`_NESTS]
|
||||
:: [s0; uppsrc bazaar reference tutorial examples]
|
||||
:: [s0; Where to look for packages]
|
||||
:: [s0; UPP`_FLAGS]
|
||||
:: [s0; GCC GUI]
|
||||
:: [s0; Build flags, same meaning as in theide]
|
||||
:: [s0; UPP`_PLATFORM]
|
||||
:: [s0; POSIX LINUX]
|
||||
:: [s0; Additional flags describing platform]
|
||||
:: [s0; UPP`_OPT]
|
||||
:: [s0; ]
|
||||
:: [s0; SPEED or SIZE to build optimized for speed or size respectively]
|
||||
:: [s0; UPP`_USEMAINCFG]
|
||||
:: [s0; 1]
|
||||
:: [s0; Whether to add flags from based on mainconfig section (1`-based
|
||||
index) or 0 to disable this feature]
|
||||
:: [s0; UPP`_INTERACTIVE]
|
||||
:: [s0; 0]
|
||||
:: [s0; Whether the parser can ask for some ]}}&]
|
||||
[s0; &]
|
||||
[s0; &]
|
||||
[s0; Make backend:&]
|
||||
[ {{2451:4582:2967h1;^ [s0; [* Variable]]
|
||||
:: [s0; [* Default]]
|
||||
::= [s0; [* Meaning]]
|
||||
::^ [s0; UPP`_OUT]
|
||||
:: [s0; /tmp/`_out]
|
||||
::=|14 [s0; See explanation of corresponding variables in Makefile.in ]
|
||||
::^ [s0; UPP`_BIN]
|
||||
:: [s0; `$(OUT)/bin]
|
||||
::= [s0;%- ]
|
||||
::^ [s0; UPP`_CFLAGS]
|
||||
:: [s0; `-O2]
|
||||
::= [s0;%- ]
|
||||
::^ [s0; UPP`_CXXFLAGS]
|
||||
:: [s0; `$(CFLAGS)]
|
||||
::= [s0;%- ]
|
||||
::^ [s0; UPP`_LDFLAGS]
|
||||
:: [s0; `-Wl,`-`-gc`-sections `-Wl,`-s `-Wl,`-O,2]
|
||||
::= [s0;%- ]
|
||||
::^ [s0; UPP`_SPEEDFLAGS]
|
||||
:: [s0; `-O3 `-ffunction`-sections `-fdata`-sections]
|
||||
::= [s0;%- ]
|
||||
::^ [s0; UPP`_SIZEFLAGS]
|
||||
:: [s0; `-Os `-finline`-limit`=20 `-ffunction`-sections `-fdata`-sections]
|
||||
::= [s0;%- ]
|
||||
::^ [s0; UPP`_INCPATHS]
|
||||
:: [s0; ]
|
||||
::= [s0;%- ]
|
||||
::^ [s0; UPP`_LIBPATHS]
|
||||
:: [s0; ]
|
||||
::= [s0;%- ]
|
||||
::^ [s0; UPP`_CXX]
|
||||
:: [s0; `$(CXX)]
|
||||
::= [s0;%- ]
|
||||
::^ [s0; UPP`_CC]
|
||||
:: [s0; `$(CC)]
|
||||
::= [s0;%- ]
|
||||
::^ [s0; UPP`_AR]
|
||||
:: [s0; ar `-src]
|
||||
::= [s0;%- ]
|
||||
::^ [s0; UPP`_DEPS]
|
||||
:: [s0; 0]
|
||||
::= [s0;%- ]
|
||||
::^ [s0; UPP`_ECHO]
|
||||
:: [s0; 0]
|
||||
::= [s0;%- ]
|
||||
::^ [s0; UPP`_SILENT]
|
||||
:: [s0; 0]
|
||||
::= [s0;%- ]}}&]
|
||||
[s0; ]
|
||||
45
uppbox/UppBuilder/update.sh
Normal file
45
uppbox/UppBuilder/update.sh
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
#!/bin/sh
|
||||
# This script compresses the parser and embeds it into
|
||||
# the Makefile, using Makefile.in template
|
||||
|
||||
echo Updating Makefile
|
||||
|
||||
# output file can be overriden by MAKEFILE_OUT variable
|
||||
[ "$MAKEFILE_OUT" ] || MAKEFILE_OUT="/tmp/Makefile"
|
||||
|
||||
{
|
||||
cat Makefile.in
|
||||
|
||||
echo '### PARSER CODE (gzipped and base64 encoded) ###'
|
||||
{
|
||||
#we perform the '#include' first
|
||||
sed '/#include PROCESS/,$d' Parser.cpp
|
||||
cat Make.hpp
|
||||
sed '1,/#include PROCESS/d' Parser.cpp
|
||||
} | gzip -9 | base64 -w74 | sed 's/.*/#:&/;'
|
||||
|
||||
echo '### BRC parser (gzipped and base64 encoded) ###'
|
||||
cat brc.sh | gzip -9 | base64 -w74 | sed 's/.*/#~&/;'
|
||||
|
||||
echo '### Colorizer (gzipped and base64 encoded) ###'
|
||||
cat color.sh | gzip -9 | base64 -w74 | sed 's/.*/#%&/;'
|
||||
} > "$MAKEFILE_OUT"
|
||||
|
||||
# little trick to ensure Makefile is always "rebuild"
|
||||
sh -c 'sleep 2 && touch Makefile.in'&
|
||||
|
||||
exit 0 # comment this line out to see compression statistics
|
||||
|
||||
stat() {
|
||||
printf "%s %5i -> %5i %3i -> %3i\n" "$1"\
|
||||
`cat $2 | wc -c` `grep $3 "$MAKEFILE_OUT" | wc -c` \
|
||||
`cat $2 | wc -l` `grep $3 "$MAKEFILE_OUT" | wc -l`
|
||||
}
|
||||
|
||||
echo "Compression info:"
|
||||
printf "%s%12s%14s\n" "File " bytes lines
|
||||
stat "Parser " Parser.cpp '^#:'
|
||||
stat "Brc parser" brc.sh '^#~'
|
||||
stat "Colorizer " color.sh '^#%'
|
||||
stat "Total " "Parser.cpp brc.sh color.sh" '^#[%~:]'
|
||||
stat "Makefile " Makefile.in '^'
|
||||
Loading…
Add table
Add a link
Reference in a new issue