1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991 |
- // astyle_main.cpp
- // Copyright (c) 2017 by Jim Pattee <jimp03@email.com>.
- // This code is licensed under the MIT License.
- // License.md describes the conditions under which this software may be distributed.
- /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- * AStyle_main source file map.
- * This source file contains several classes.
- * They are arranged as follows.
- * ---------------------------------------
- * namespace astyle {
- * ASStreamIterator methods
- * ASConsole methods
- * // Windows specific
- * // Linux specific
- * ASLibrary methods
- * // Windows specific
- * // Linux specific
- * ASOptions methods
- * ASEncoding methods
- * } // end of astyle namespace
- * Global Area ---------------------------
- * Java Native Interface functions
- * AStyleMainUtf16 entry point
- * AStyleMain entry point
- * AStyleGetVersion entry point
- * main entry point
- * ---------------------------------------
- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
- */
- //-----------------------------------------------------------------------------
- // headers
- //-----------------------------------------------------------------------------
- #include "astyle_main.h"
- #include <algorithm>
- #include <cerrno>
- #include <clocale> // needed by some compilers
- #include <cstdlib>
- #include <fstream>
- #include <sstream>
- // includes for recursive getFileNames() function
- #ifdef _WIN32
- #undef UNICODE // use ASCII windows functions
- #include <windows.h>
- #else
- #include <dirent.h>
- #include <unistd.h>
- #include <sys/stat.h>
- #ifdef __VMS
- #include <unixlib.h>
- #include <rms.h>
- #include <ssdef.h>
- #include <stsdef.h>
- #include <lib$routines.h>
- #include <starlet.h>
- #endif /* __VMS */
- #endif
- //-----------------------------------------------------------------------------
- // declarations
- //-----------------------------------------------------------------------------
- // turn off MinGW automatic file globbing
- // this CANNOT be in the astyle namespace
- #ifndef ASTYLE_LIB
- int _CRT_glob = 0;
- #endif
- //----------------------------------------------------------------------------
- // astyle namespace
- //----------------------------------------------------------------------------
- namespace astyle {
- //
- // console build variables
- #ifndef ASTYLE_LIB
- #ifdef _WIN32
- char g_fileSeparator = '\\'; // Windows file separator
- bool g_isCaseSensitive = false; // Windows IS NOT case sensitive
- #else
- char g_fileSeparator = '/'; // Linux file separator
- bool g_isCaseSensitive = true; // Linux IS case sensitive
- #endif // _WIN32
- #endif // ASTYLE_LIB
- // java library build variables
- #ifdef ASTYLE_JNI
- JNIEnv* g_env;
- jobject g_obj;
- jmethodID g_mid;
- #endif
- const char* g_version = "3.0";
- //-----------------------------------------------------------------------------
- // ASStreamIterator class
- // typename will be istringstream for GUI and istream otherwise
- //-----------------------------------------------------------------------------
- template<typename T>
- ASStreamIterator<T>::ASStreamIterator(T* in)
- {
- inStream = in;
- buffer.reserve(200);
- eolWindows = 0;
- eolLinux = 0;
- eolMacOld = 0;
- peekStart = 0;
- prevLineDeleted = false;
- checkForEmptyLine = false;
- // get length of stream
- inStream->seekg(0, inStream->end);
- streamLength = inStream->tellg();
- inStream->seekg(0, inStream->beg);
- }
- template<typename T>
- ASStreamIterator<T>::~ASStreamIterator()
- {
- }
- /**
- * get the length of the input stream.
- * streamLength variable is set by the constructor.
- *
- * @return length of the input file stream, converted to an int.
- */
- template<typename T>
- int ASStreamIterator<T>::getStreamLength() const
- {
- return static_cast<int>(streamLength);
- }
- /**
- * read the input stream, delete any end of line characters,
- * and build a string that contains the input line.
- *
- * @return string containing the next input line minus any end of line characters
- */
- template<typename T>
- string ASStreamIterator<T>::nextLine(bool emptyLineWasDeleted)
- {
- // verify that the current position is correct
- assert(peekStart == 0);
- // a deleted line may be replaced if break-blocks is requested
- // this sets up the compare to check for a replaced empty line
- if (prevLineDeleted)
- {
- prevLineDeleted = false;
- checkForEmptyLine = true;
- }
- if (!emptyLineWasDeleted)
- prevBuffer = buffer;
- else
- prevLineDeleted = true;
- // read the next record
- buffer.clear();
- char ch;
- inStream->get(ch);
- while (!inStream->eof() && ch != '\n' && ch != '\r')
- {
- buffer.append(1, ch);
- inStream->get(ch);
- }
- if (inStream->eof())
- {
- return buffer;
- }
- int peekCh = inStream->peek();
- // find input end-of-line characters
- if (!inStream->eof())
- {
- if (ch == '\r') // CR+LF is windows otherwise Mac OS 9
- {
- if (peekCh == '\n')
- {
- inStream->get();
- eolWindows++;
- }
- else
- eolMacOld++;
- }
- else // LF is Linux, allow for improbable LF/CR
- {
- if (peekCh == '\r')
- {
- inStream->get();
- eolWindows++;
- }
- else
- eolLinux++;
- }
- }
- else
- {
- inStream->clear();
- }
- // set output end of line characters
- if (eolWindows >= eolLinux)
- {
- if (eolWindows >= eolMacOld)
- outputEOL = "\r\n"; // Windows (CR+LF)
- else
- outputEOL = "\r"; // MacOld (CR)
- }
- else if (eolLinux >= eolMacOld)
- outputEOL = "\n"; // Linux (LF)
- else
- outputEOL = "\r"; // MacOld (CR)
- return buffer;
- }
- // save the current position and get the next line
- // this can be called for multiple reads
- // when finished peeking you MUST call peekReset()
- // call this function from ASFormatter ONLY
- template<typename T>
- string ASStreamIterator<T>::peekNextLine()
- {
- assert(hasMoreLines());
- string nextLine_;
- char ch;
- if (peekStart == 0)
- peekStart = inStream->tellg();
- // read the next record
- inStream->get(ch);
- while (!inStream->eof() && ch != '\n' && ch != '\r')
- {
- nextLine_.append(1, ch);
- inStream->get(ch);
- }
- if (inStream->eof())
- {
- return nextLine_;
- }
- int peekCh = inStream->peek();
- // remove end-of-line characters
- if (!inStream->eof())
- {
- if ((peekCh == '\n' || peekCh == '\r') && peekCh != ch)
- inStream->get();
- }
- return nextLine_;
- }
- // reset current position and EOF for peekNextLine()
- template<typename T>
- void ASStreamIterator<T>::peekReset()
- {
- assert(peekStart != 0);
- inStream->clear();
- inStream->seekg(peekStart);
- peekStart = 0;
- }
- // save the last input line after input has reached EOF
- template<typename T>
- void ASStreamIterator<T>::saveLastInputLine()
- {
- assert(inStream->eof());
- prevBuffer = buffer;
- }
- // return position of the get pointer
- template<typename T>
- streamoff ASStreamIterator<T>::tellg()
- {
- return inStream->tellg();
- }
- // check for a change in line ends
- template<typename T>
- bool ASStreamIterator<T>::getLineEndChange(int lineEndFormat) const
- {
- assert(lineEndFormat == LINEEND_DEFAULT
- || lineEndFormat == LINEEND_WINDOWS
- || lineEndFormat == LINEEND_LINUX
- || lineEndFormat == LINEEND_MACOLD);
- bool lineEndChange = false;
- if (lineEndFormat == LINEEND_WINDOWS)
- lineEndChange = (eolLinux + eolMacOld != 0);
- else if (lineEndFormat == LINEEND_LINUX)
- lineEndChange = (eolWindows + eolMacOld != 0);
- else if (lineEndFormat == LINEEND_MACOLD)
- lineEndChange = (eolWindows + eolLinux != 0);
- else
- {
- if (eolWindows > 0)
- lineEndChange = (eolLinux + eolMacOld != 0);
- else if (eolLinux > 0)
- lineEndChange = (eolWindows + eolMacOld != 0);
- else if (eolMacOld > 0)
- lineEndChange = (eolWindows + eolLinux != 0);
- }
- return lineEndChange;
- }
- //-----------------------------------------------------------------------------
- // ASConsole class
- // main function will be included only in the console build
- //-----------------------------------------------------------------------------
- #ifndef ASTYLE_LIB
- ASConsole::ASConsole(ASFormatter& formatterArg) : formatter(formatterArg)
- {
- errorStream = &cerr;
- // command line options
- isRecursive = false;
- isDryRun = false;
- noBackup = false;
- preserveDate = false;
- isVerbose = false;
- isQuiet = false;
- isFormattedOnly = false;
- ignoreExcludeErrors = false;
- ignoreExcludeErrorsDisplay = false;
- optionsFileRequired = false;
- useAscii = false;
- // other variables
- bypassBrowserOpen = false;
- hasWildcard = false;
- filesAreIdentical = true;
- lineEndsMixed = false;
- origSuffix = ".orig";
- mainDirectoryLength = 0;
- filesFormatted = 0;
- filesUnchanged = 0;
- linesOut = 0;
- }
- ASConsole::~ASConsole()
- {}
- // rewrite a stringstream converting the line ends
- void ASConsole::convertLineEnds(ostringstream& out, int lineEnd)
- {
- assert(lineEnd == LINEEND_WINDOWS || lineEnd == LINEEND_LINUX || lineEnd == LINEEND_MACOLD);
- const string& inStr = out.str(); // avoids strange looking syntax
- string outStr; // the converted output
- int inLength = (int)inStr.length();
- for (int pos = 0; pos < inLength; pos++)
- {
- if (inStr[pos] == '\r')
- {
- if (inStr[pos + 1] == '\n')
- {
- // CRLF
- if (lineEnd == LINEEND_CR)
- {
- outStr += inStr[pos]; // Delete the LF
- pos++;
- continue;
- }
- else if (lineEnd == LINEEND_LF)
- {
- outStr += inStr[pos + 1]; // Delete the CR
- pos++;
- continue;
- }
- else
- {
- outStr += inStr[pos]; // Do not change
- outStr += inStr[pos + 1];
- pos++;
- continue;
- }
- }
- else
- {
- // CR
- if (lineEnd == LINEEND_CRLF)
- {
- outStr += inStr[pos]; // Insert the CR
- outStr += '\n'; // Insert the LF
- continue;
- }
- else if (lineEnd == LINEEND_LF)
- {
- outStr += '\n'; // Insert the LF
- continue;
- }
- else
- {
- outStr += inStr[pos]; // Do not change
- continue;
- }
- }
- }
- else if (inStr[pos] == '\n')
- {
- // LF
- if (lineEnd == LINEEND_CRLF)
- {
- outStr += '\r'; // Insert the CR
- outStr += inStr[pos]; // Insert the LF
- continue;
- }
- else if (lineEnd == LINEEND_CR)
- {
- outStr += '\r'; // Insert the CR
- continue;
- }
- else
- {
- outStr += inStr[pos]; // Do not change
- continue;
- }
- }
- else
- {
- outStr += inStr[pos]; // Write the current char
- }
- }
- // replace the stream
- out.str(outStr);
- }
- void ASConsole::correctMixedLineEnds(ostringstream& out)
- {
- LineEndFormat lineEndFormat = LINEEND_DEFAULT;
- if (outputEOL == "\r\n")
- lineEndFormat = LINEEND_WINDOWS;
- if (outputEOL == "\n")
- lineEndFormat = LINEEND_LINUX;
- if (outputEOL == "\r")
- lineEndFormat = LINEEND_MACOLD;
- convertLineEnds(out, lineEndFormat);
- }
- // check files for 16 or 32 bit encoding
- // the file must have a Byte Order Mark (BOM)
- // NOTE: some string functions don't work with NULLs (e.g. length())
- FileEncoding ASConsole::detectEncoding(const char* data, size_t dataSize) const
- {
- FileEncoding encoding = ENCODING_8BIT;
- if (dataSize >= 4 && memcmp(data, "\x00\x00\xFE\xFF", 4) == 0)
- encoding = UTF_32BE;
- else if (dataSize >= 4 && memcmp(data, "\xFF\xFE\x00\x00", 4) == 0)
- encoding = UTF_32LE;
- else if (dataSize >= 2 && memcmp(data, "\xFE\xFF", 2) == 0)
- encoding = UTF_16BE;
- else if (dataSize >= 2 && memcmp(data, "\xFF\xFE", 2) == 0)
- encoding = UTF_16LE;
- return encoding;
- }
- // error exit without a message
- void ASConsole::error() const
- {
- (*errorStream) << _("\nArtistic Style has terminated") << endl;
- exit(EXIT_FAILURE);
- }
- // error exit with a message
- void ASConsole::error(const char* why, const char* what) const
- {
- (*errorStream) << why << ' ' << what << endl;
- error();
- }
- /**
- * If no files have been given, use cin for input and cout for output.
- *
- * This is used to format text for text editors like TextWrangler (Mac).
- * Do NOT display any console messages when this function is used.
- */
- void ASConsole::formatCinToCout()
- {
- // check for files from --stdin= and --stdout=
- if (!stdPathIn.empty())
- {
- if (!freopen(stdPathIn.c_str(), "r", stdin))
- error("Cannot open input file", stdPathIn.c_str());
- }
- if (!stdPathOut.empty())
- {
- if (!freopen(stdPathOut.c_str(), "w", stdout))
- error("Cannot open output file", stdPathOut.c_str());
- }
- // Using cin.tellg() causes problems with both Windows and Linux.
- // The Windows problem occurs when the input is not Windows line-ends.
- // The tellg() will be out of sequence with the get() statements.
- // The Linux cin.tellg() will return -1 (invalid).
- // Copying the input sequentially to a stringstream before
- // formatting solves the problem for both.
- istream* inStream = &cin;
- stringstream outStream;
- char ch;
- inStream->get(ch);
- while (!inStream->eof() && !inStream->fail())
- {
- outStream.put(ch);
- inStream->get(ch);
- }
- ASStreamIterator<stringstream> streamIterator(&outStream);
- // Windows pipe or redirection always outputs Windows line-ends.
- // Linux pipe or redirection will output any line end.
- #ifdef _WIN32
- LineEndFormat lineEndFormat = LINEEND_DEFAULT;
- #else
- LineEndFormat lineEndFormat = formatter.getLineEndFormat();
- #endif // _WIN32
- initializeOutputEOL(lineEndFormat);
- formatter.init(&streamIterator);
- while (formatter.hasMoreLines())
- {
- cout << formatter.nextLine();
- if (formatter.hasMoreLines())
- {
- setOutputEOL(lineEndFormat, streamIterator.getOutputEOL());
- cout << outputEOL;
- }
- else
- {
- // this can happen if the file if missing a closing brace and break-blocks is requested
- if (formatter.getIsLineReady())
- {
- setOutputEOL(lineEndFormat, streamIterator.getOutputEOL());
- cout << outputEOL;
- cout << formatter.nextLine();
- }
- }
- }
- cout.flush();
- }
- /**
- * Open input file, format it, and close the output.
- *
- * @param fileName_ The path and name of the file to be processed.
- */
- void ASConsole::formatFile(const string& fileName_)
- {
- stringstream in;
- ostringstream out;
- FileEncoding encoding = readFile(fileName_, in);
- // Unless a specific language mode has been set, set the language mode
- // according to the file's suffix.
- if (!formatter.getModeManuallySet())
- {
- if (stringEndsWith(fileName_, string(".java")))
- formatter.setJavaStyle();
- else if (stringEndsWith(fileName_, string(".cs")))
- formatter.setSharpStyle();
- else
- formatter.setCStyle();
- }
- // set line end format
- string nextLine; // next output line
- filesAreIdentical = true; // input and output files are identical
- LineEndFormat lineEndFormat = formatter.getLineEndFormat();
- initializeOutputEOL(lineEndFormat);
- // do this AFTER setting the file mode
- ASStreamIterator<stringstream> streamIterator(&in);
- formatter.init(&streamIterator);
- // format the file
- while (formatter.hasMoreLines())
- {
- nextLine = formatter.nextLine();
- out << nextLine;
- linesOut++;
- if (formatter.hasMoreLines())
- {
- setOutputEOL(lineEndFormat, streamIterator.getOutputEOL());
- out << outputEOL;
- }
- else
- {
- streamIterator.saveLastInputLine(); // to compare the last input line
- // this can happen if the file if missing a closing brace and break-blocks is requested
- if (formatter.getIsLineReady())
- {
- setOutputEOL(lineEndFormat, streamIterator.getOutputEOL());
- out << outputEOL;
- nextLine = formatter.nextLine();
- out << nextLine;
- linesOut++;
- streamIterator.saveLastInputLine();
- }
- }
- if (filesAreIdentical)
- {
- if (streamIterator.checkForEmptyLine)
- {
- if (nextLine.find_first_not_of(" \t") != string::npos)
- filesAreIdentical = false;
- }
- else if (!streamIterator.compareToInputBuffer(nextLine))
- filesAreIdentical = false;
- streamIterator.checkForEmptyLine = false;
- }
- }
- // correct for mixed line ends
- if (lineEndsMixed)
- {
- correctMixedLineEnds(out);
- filesAreIdentical = false;
- }
- // remove targetDirectory from filename if required by print
- string displayName;
- if (hasWildcard)
- displayName = fileName_.substr(targetDirectory.length() + 1);
- else
- displayName = fileName_;
- // if file has changed, write the new file
- if (!filesAreIdentical || streamIterator.getLineEndChange(lineEndFormat))
- {
- if (!isDryRun)
- writeFile(fileName_, encoding, out);
- printMsg(_("Formatted %s\n"), displayName);
- filesFormatted++;
- }
- else
- {
- if (!isFormattedOnly)
- printMsg(_("Unchanged %s\n"), displayName);
- filesUnchanged++;
- }
- assert(formatter.getChecksumDiff() == 0);
- }
- // build a vector of argv options
- // the program path argv[0] is excluded
- vector<string> ASConsole::getArgvOptions(int argc, char** argv) const
- {
- vector<string> argvOptions;
- for (int i = 1; i < argc; i++)
- {
- argvOptions.emplace_back(string(argv[i]));
- }
- return argvOptions;
- }
- // for unit testing
- vector<bool> ASConsole::getExcludeHitsVector() const
- { return excludeHitsVector; }
- // for unit testing
- vector<string> ASConsole::getExcludeVector() const
- { return excludeVector; }
- // for unit testing
- vector<string> ASConsole::getFileName() const
- { return fileName; }
- // for unit testing
- vector<string> ASConsole::getFileNameVector() const
- { return fileNameVector; }
- // for unit testing
- vector<string> ASConsole::getFileOptionsVector() const
- { return fileOptionsVector; }
- // for unit testing
- bool ASConsole::getFilesAreIdentical() const
- { return filesAreIdentical; }
- // for unit testing
- int ASConsole::getFilesFormatted() const
- { return filesFormatted; }
- // for unit testing
- bool ASConsole::getIgnoreExcludeErrors() const
- { return ignoreExcludeErrors; }
- // for unit testing
- bool ASConsole::getIgnoreExcludeErrorsDisplay() const
- { return ignoreExcludeErrorsDisplay; }
- // for unit testing
- bool ASConsole::getIsDryRun() const
- { return isDryRun; }
- // for unit testing
- bool ASConsole::getIsFormattedOnly() const
- { return isFormattedOnly; }
- // for unit testing
- string ASConsole::getLanguageID() const
- { return localizer.getLanguageID(); }
- // for unit testing
- bool ASConsole::getIsQuiet() const
- { return isQuiet; }
- // for unit testing
- bool ASConsole::getIsRecursive() const
- { return isRecursive; }
- // for unit testing
- bool ASConsole::getIsVerbose() const
- { return isVerbose; }
- // for unit testing
- bool ASConsole::getLineEndsMixed() const
- { return lineEndsMixed; }
- // for unit testing
- bool ASConsole::getNoBackup() const
- { return noBackup; }
- // for unit testing
- string ASConsole::getOptionsFileName() const
- { return optionsFileName; }
- // for unit testing
- vector<string> ASConsole::getOptionsVector() const
- { return optionsVector; }
- // for unit testing
- string ASConsole::getOrigSuffix() const
- { return origSuffix; }
- // for unit testing
- bool ASConsole::getPreserveDate() const
- { return preserveDate; }
- // for unit testing
- string ASConsole::getStdPathIn() const
- { return stdPathIn; }
- // for unit testing
- string ASConsole::getStdPathOut() const
- { return stdPathOut; }
- // for unit testing
- void ASConsole::setBypassBrowserOpen(bool state)
- { bypassBrowserOpen = state; }
- // for unit testing
- ostream* ASConsole::getErrorStream() const
- {
- return errorStream;
- }
- void ASConsole::setErrorStream(ostream* errStreamPtr)
- {
- errorStream = errStreamPtr;
- }
- string ASConsole::getParam(const string& arg, const char* op)
- {
- return arg.substr(strlen(op));
- }
- // initialize output end of line
- void ASConsole::initializeOutputEOL(LineEndFormat lineEndFormat)
- {
- assert(lineEndFormat == LINEEND_DEFAULT
- || lineEndFormat == LINEEND_WINDOWS
- || lineEndFormat == LINEEND_LINUX
- || lineEndFormat == LINEEND_MACOLD);
- outputEOL.clear(); // current line end
- prevEOL.clear(); // previous line end
- lineEndsMixed = false; // output has mixed line ends, LINEEND_DEFAULT only
- if (lineEndFormat == LINEEND_WINDOWS)
- outputEOL = "\r\n";
- else if (lineEndFormat == LINEEND_LINUX)
- outputEOL = "\n";
- else if (lineEndFormat == LINEEND_MACOLD)
- outputEOL = "\r";
- else
- outputEOL.clear();
- }
- FileEncoding ASConsole::readFile(const string& fileName_, stringstream& in) const
- {
- const int blockSize = 65536; // 64 KB
- ifstream fin(fileName_.c_str(), ios::binary);
- if (!fin)
- error("Cannot open input file", fileName_.c_str());
- char* data = new (nothrow) char[blockSize];
- if (data == nullptr)
- error("Cannot allocate memory for input file", fileName_.c_str());
- fin.read(data, blockSize);
- if (fin.bad())
- error("Cannot read input file", fileName_.c_str());
- size_t dataSize = static_cast<size_t>(fin.gcount());
- FileEncoding encoding = detectEncoding(data, dataSize);
- if (encoding == UTF_32BE || encoding == UTF_32LE)
- error(_("Cannot process UTF-32 encoding"), fileName_.c_str());
- bool firstBlock = true;
- bool isBigEndian = (encoding == UTF_16BE);
- while (dataSize != 0)
- {
- if (encoding == UTF_16LE || encoding == UTF_16BE)
- {
- // convert utf-16 to utf-8
- size_t utf8Size = utf8_16.utf8LengthFromUtf16(data, dataSize, isBigEndian);
- char* utf8Out = new (nothrow) char[utf8Size];
- if (utf8Out == nullptr)
- error("Cannot allocate memory for utf-8 conversion", fileName_.c_str());
- size_t utf8Len = utf8_16.utf16ToUtf8(data, dataSize, isBigEndian, firstBlock, utf8Out);
- assert(utf8Len == utf8Size);
- in << string(utf8Out, utf8Len);
- delete[] utf8Out;
- }
- else
- in << string(data, dataSize);
- fin.read(data, blockSize);
- if (fin.bad())
- error("Cannot read input file", fileName_.c_str());
- dataSize = static_cast<size_t>(fin.gcount());
- firstBlock = false;
- }
- fin.close();
- delete[] data;
- return encoding;
- }
- void ASConsole::setIgnoreExcludeErrors(bool state)
- { ignoreExcludeErrors = state; }
- void ASConsole::setIgnoreExcludeErrorsAndDisplay(bool state)
- { ignoreExcludeErrors = state; ignoreExcludeErrorsDisplay = state; }
- void ASConsole::setIsFormattedOnly(bool state)
- { isFormattedOnly = state; }
- void ASConsole::setIsQuiet(bool state)
- { isQuiet = state; }
- void ASConsole::setIsRecursive(bool state)
- { isRecursive = state; }
- void ASConsole::setIsDryRun(bool state)
- { isDryRun = state; }
- void ASConsole::setIsVerbose(bool state)
- { isVerbose = state; }
- void ASConsole::setNoBackup(bool state)
- { noBackup = state; }
- void ASConsole::setOptionsFileName(const string& name)
- { optionsFileName = name; }
- void ASConsole::setOrigSuffix(const string& suffix)
- { origSuffix = suffix; }
- void ASConsole::setPreserveDate(bool state)
- { preserveDate = state; }
- void ASConsole::setStdPathIn(const string& path)
- { stdPathIn = path; }
- void ASConsole::setStdPathOut(const string& path)
- { stdPathOut = path; }
- // set outputEOL variable
- void ASConsole::setOutputEOL(LineEndFormat lineEndFormat, const string& currentEOL)
- {
- if (lineEndFormat == LINEEND_DEFAULT)
- {
- outputEOL = currentEOL;
- if (prevEOL.empty())
- prevEOL = outputEOL;
- if (prevEOL != outputEOL)
- {
- lineEndsMixed = true;
- filesAreIdentical = false;
- prevEOL = outputEOL;
- }
- }
- else
- {
- prevEOL = currentEOL;
- if (prevEOL != outputEOL)
- filesAreIdentical = false;
- }
- }
- #ifdef _WIN32 // Windows specific
- /**
- * WINDOWS function to display the last system error.
- */
- void ASConsole::displayLastError()
- {
- LPSTR msgBuf;
- DWORD lastError = GetLastError();
- FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
- nullptr,
- lastError,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
- (LPSTR) &msgBuf,
- 0,
- nullptr
- );
- // Display the string.
- (*errorStream) << "Error (" << lastError << ") " << msgBuf << endl;
- // Free the buffer.
- LocalFree(msgBuf);
- }
- /**
- * WINDOWS function to get the current directory.
- * NOTE: getenv("CD") does not work for Windows Vista.
- * The Windows function GetCurrentDirectory is used instead.
- *
- * @return The path of the current directory
- */
- string ASConsole::getCurrentDirectory(const string& fileName_) const
- {
- char currdir[MAX_PATH];
- currdir[0] = '\0';
- if (!GetCurrentDirectory(sizeof(currdir), currdir))
- error("Cannot find file", fileName_.c_str());
- return string(currdir);
- }
- /**
- * WINDOWS function to resolve wildcards and recurse into sub directories.
- * The fileName vector is filled with the path and names of files to process.
- *
- * @param directory The path of the directory to be processed.
- * @param wildcard The wildcard to be processed (e.g. *.cpp).
- */
- void ASConsole::getFileNames(const string& directory, const string& wildcard)
- {
- vector<string> subDirectory; // sub directories of directory
- WIN32_FIND_DATA findFileData; // for FindFirstFile and FindNextFile
- // Find the first file in the directory
- // Find will get at least "." and "..".
- string firstFile = directory + "\\*";
- HANDLE hFind = FindFirstFile(firstFile.c_str(), &findFileData);
- if (hFind == INVALID_HANDLE_VALUE)
- {
- // Error (3) The system cannot find the path specified.
- // Error (123) The filename, directory name, or volume label syntax is incorrect.
- // ::FindClose(hFind); before exiting
- displayLastError();
- error(_("Cannot open directory"), directory.c_str());
- }
- // save files and sub directories
- do
- {
- // skip hidden or read only
- if (findFileData.cFileName[0] == '.'
- || (findFileData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN)
- || (findFileData.dwFileAttributes & FILE_ATTRIBUTE_READONLY))
- continue;
- // is this a sub directory
- if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- {
- if (!isRecursive)
- continue;
- // if a sub directory and recursive, save sub directory
- string subDirectoryPath = directory + g_fileSeparator + findFileData.cFileName;
- if (isPathExclued(subDirectoryPath))
- printMsg(_("Exclude %s\n"), subDirectoryPath.substr(mainDirectoryLength));
- else
- subDirectory.emplace_back(subDirectoryPath);
- continue;
- }
- // save the file name
- string filePathName = directory + g_fileSeparator + findFileData.cFileName;
- // check exclude before wildcmp to avoid "unmatched exclude" error
- bool isExcluded = isPathExclued(filePathName);
- // save file name if wildcard match
- if (wildcmp(wildcard.c_str(), findFileData.cFileName))
- {
- if (isExcluded)
- printMsg(_("Exclude %s\n"), filePathName.substr(mainDirectoryLength));
- else
- fileName.emplace_back(filePathName);
- }
- }
- while (FindNextFile(hFind, &findFileData) != 0);
- // check for processing error
- ::FindClose(hFind);
- DWORD dwError = GetLastError();
- if (dwError != ERROR_NO_MORE_FILES)
- error("Error processing directory", directory.c_str());
- // recurse into sub directories
- // if not doing recursive subDirectory is empty
- for (unsigned i = 0; i < subDirectory.size(); i++)
- getFileNames(subDirectory[i], wildcard);
- return;
- }
- /**
- * WINDOWS function to format a number according to the current locale.
- * This formats positive integers only, no float.
- *
- * @param num The number to be formatted.
- * @param lcid The LCID of the locale to be used for testing.
- * @return The formatted number.
- */
- string ASConsole::getNumberFormat(int num, size_t lcid) const
- {
- #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__BORLANDC__) || defined(__GNUC__)
- // Compilers that don't support C++ locales should still support this assert.
- // The C locale should be set but not the C++.
- // This function is not necessary if the C++ locale is set.
- // The locale().name() return value is not portable to all compilers.
- assert(locale().name() == "C");
- #endif
- // convert num to a string
- stringstream alphaNum;
- alphaNum << num;
- string number = alphaNum.str();
- if (useAscii)
- return number;
- // format the number using the Windows API
- if (lcid == 0)
- lcid = LOCALE_USER_DEFAULT;
- int outSize = ::GetNumberFormat(lcid, 0, number.c_str(), nullptr, nullptr, 0);
- char* outBuf = new (nothrow) char[outSize];
- if (outBuf == nullptr)
- return number;
- ::GetNumberFormat(lcid, 0, number.c_str(), nullptr, outBuf, outSize);
- string formattedNum(outBuf);
- delete[] outBuf;
- // remove the decimal
- int decSize = ::GetLocaleInfo(lcid, LOCALE_SDECIMAL, nullptr, 0);
- char* decBuf = new (nothrow) char[decSize];
- if (decBuf == nullptr)
- return number;
- ::GetLocaleInfo(lcid, LOCALE_SDECIMAL, decBuf, decSize);
- size_t i = formattedNum.rfind(decBuf);
- delete[] decBuf;
- if (i != string::npos)
- formattedNum.erase(i);
- if (!formattedNum.length())
- formattedNum = "0";
- return formattedNum;
- }
- /**
- * WINDOWS function to open a HTML file in the default browser.
- */
- void ASConsole::launchDefaultBrowser(const char* filePathIn /*nullptr*/) const
- {
- struct stat statbuf;
- const char* envPaths[] = { "PROGRAMFILES(X86)", "PROGRAMFILES" };
- size_t pathsLen = sizeof(envPaths) / sizeof(envPaths[0]);
- string htmlDefaultPath;
- for (size_t i = 0; i < pathsLen; i++)
- {
- const char* envPath = getenv(envPaths[i]);
- if (envPath == nullptr)
- continue;
- htmlDefaultPath = envPath;
- if (htmlDefaultPath.length() > 0
- && htmlDefaultPath[htmlDefaultPath.length() - 1] == g_fileSeparator)
- htmlDefaultPath.erase(htmlDefaultPath.length() - 1);
- htmlDefaultPath.append("\\AStyle\\doc");
- if (stat(htmlDefaultPath.c_str(), &statbuf) == 0 && statbuf.st_mode & S_IFDIR)
- break;
- }
- htmlDefaultPath.append("\\");
- // build file path
- string htmlFilePath;
- if (filePathIn == nullptr)
- htmlFilePath = htmlDefaultPath + "astyle.html";
- else
- {
- if (strpbrk(filePathIn, "\\/") == nullptr)
- htmlFilePath = htmlDefaultPath + filePathIn;
- else
- htmlFilePath = filePathIn;
- }
- standardizePath(htmlFilePath);
- if (stat(htmlFilePath.c_str(), &statbuf) != 0 || !(statbuf.st_mode & S_IFREG))
- {
- printf(_("Cannot open HTML file %s\n"), htmlFilePath.c_str());
- return;
- }
- SHELLEXECUTEINFO sei = { sizeof(sei), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- sei.fMask = SEE_MASK_FLAG_NO_UI;
- sei.lpVerb = "open";
- sei.lpFile = htmlFilePath.c_str();
- sei.nShow = SW_SHOWNORMAL;
- // browser open will be bypassed in test programs
- printf(_("Opening HTML documentation %s\n"), htmlFilePath.c_str());
- if (!bypassBrowserOpen)
- {
- int ret = ShellExecuteEx(&sei);
- if (!ret)
- error(_("Command execute failure"), htmlFilePath.c_str());
- }
- }
- #else // Linux specific
- /**
- * LINUX function to get the current directory.
- * This is done if the fileName does not contain a path.
- * It is probably from an editor sending a single file.
- *
- * @param fileName_ The filename is used only for the error message.
- * @return The path of the current directory
- */
- string ASConsole::getCurrentDirectory(const string& fileName_) const
- {
- char* currdir = getenv("PWD");
- if (currdir == nullptr)
- error("Cannot find file", fileName_.c_str());
- return string(currdir);
- }
- /**
- * LINUX function to resolve wildcards and recurse into sub directories.
- * The fileName vector is filled with the path and names of files to process.
- *
- * @param directory The path of the directory to be processed.
- * @param wildcard The wildcard to be processed (e.g. *.cpp).
- */
- void ASConsole::getFileNames(const string& directory, const string& wildcard)
- {
- struct dirent* entry; // entry from readdir()
- struct stat statbuf; // entry from stat()
- vector<string> subDirectory; // sub directories of this directory
- // errno is defined in <errno.h> and is set for errors in opendir, readdir, or stat
- errno = 0;
- DIR* dp = opendir(directory.c_str());
- if (dp == nullptr)
- error(_("Cannot open directory"), directory.c_str());
- // save the first fileName entry for this recursion
- const unsigned firstEntry = fileName.size();
- // save files and sub directories
- while ((entry = readdir(dp)) != nullptr)
- {
- // get file status
- string entryFilepath = directory + g_fileSeparator + entry->d_name;
- if (stat(entryFilepath.c_str(), &statbuf) != 0)
- {
- if (errno == EOVERFLOW) // file over 2 GB is OK
- {
- errno = 0;
- continue;
- }
- perror("errno message");
- error("Error getting file status in directory", directory.c_str());
- }
- // skip hidden or read only
- if (entry->d_name[0] == '.' || !(statbuf.st_mode & S_IWUSR))
- continue;
- // if a sub directory and recursive, save sub directory
- if (S_ISDIR(statbuf.st_mode) && isRecursive)
- {
- if (isPathExclued(entryFilepath))
- printMsg(_("Exclude %s\n"), entryFilepath.substr(mainDirectoryLength));
- else
- subDirectory.emplace_back(entryFilepath);
- continue;
- }
- // if a file, save file name
- if (S_ISREG(statbuf.st_mode))
- {
- // check exclude before wildcmp to avoid "unmatched exclude" error
- bool isExcluded = isPathExclued(entryFilepath);
- // save file name if wildcard match
- if (wildcmp(wildcard.c_str(), entry->d_name) != 0)
- {
- if (isExcluded)
- printMsg(_("Exclude %s\n"), entryFilepath.substr(mainDirectoryLength));
- else
- fileName.emplace_back(entryFilepath);
- }
- }
- }
- if (closedir(dp) != 0)
- {
- perror("errno message");
- error("Error reading directory", directory.c_str());
- }
- // sort the current entries for fileName
- if (firstEntry < fileName.size())
- sort(&fileName[firstEntry], &fileName[fileName.size()]);
- // recurse into sub directories
- // if not doing recursive, subDirectory is empty
- if (subDirectory.size() > 1)
- sort(subDirectory.begin(), subDirectory.end());
- for (unsigned i = 0; i < subDirectory.size(); i++)
- {
- getFileNames(subDirectory[i], wildcard);
- }
- }
- /**
- * LINUX function to get locale information and call getNumberFormat.
- * This formats positive integers only, no float.
- *
- * @param num The number to be formatted.
- * size_t is for compatibility with the Windows function.
- * @return The formatted number.
- */
- string ASConsole::getNumberFormat(int num, size_t /*lcid*/) const
- {
- #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__BORLANDC__) || defined(__GNUC__)
- // Compilers that don't support C++ locales should still support this assert.
- // The C locale should be set but not the C++.
- // This function is not necessary if the C++ locale is set.
- // The locale().name() return value is not portable to all compilers.
- assert(locale().name() == "C");
- #endif
- // get the locale info
- struct lconv* lc;
- lc = localeconv();
- // format the number
- return getNumberFormat(num, lc->grouping, lc->thousands_sep);
- }
- /**
- * LINUX function to format a number according to the current locale.
- * This formats positive integers only, no float.
- *
- * @param num The number to be formatted.
- * @param groupingArg The grouping string from the locale.
- * @param separator The thousands group separator from the locale.
- * @return The formatted number.
- */
- string ASConsole::getNumberFormat(int num, const char* groupingArg, const char* separator) const
- {
- // convert num to a string
- stringstream alphaNum;
- alphaNum << num;
- string number = alphaNum.str();
- // format the number from right to left
- string formattedNum;
- size_t ig = 0; // grouping index
- int grouping = groupingArg[ig];
- int i = number.length();
- // check for no grouping
- if (grouping == 0)
- grouping = number.length();
- while (i > 0)
- {
- // extract a group of numbers
- string group;
- if (i < grouping)
- group = number;
- else
- group = number.substr(i - grouping);
- // update formatted number
- formattedNum.insert(0, group);
- i -= grouping;
- if (i < 0)
- i = 0;
- if (i > 0)
- formattedNum.insert(0, separator);
- number.erase(i);
- // update grouping
- if (groupingArg[ig] != '\0'
- && groupingArg[ig + 1] != '\0')
- grouping = groupingArg[++ig];
- }
- return formattedNum;
- }
- /**
- * LINUX function to open a HTML file in the default browser.
- * Use xdg-open from freedesktop.org cross-desktop compatibility suite xdg-utils.
- * see http://portland.freedesktop.org/wiki/
- * This is installed on most modern distributions.
- */
- void ASConsole::launchDefaultBrowser(const char* filePathIn /*nullptr*/) const
- {
- struct stat statbuf;
- string htmlDefaultPath = "/usr/share/doc/astyle/html/";
- string htmlDefaultFile = "astyle.html";
- // build file path
- string htmlFilePath;
- if (filePathIn == nullptr)
- htmlFilePath = htmlDefaultPath + htmlDefaultFile;
- else
- {
- if (strpbrk(filePathIn, "\\/") == nullptr)
- htmlFilePath = htmlDefaultPath + filePathIn;
- else
- htmlFilePath = filePathIn;
- }
- standardizePath(htmlFilePath);
- if (stat(htmlFilePath.c_str(), &statbuf) != 0 || !(statbuf.st_mode & S_IFREG))
- {
- printf(_("Cannot open HTML file %s\n"), htmlFilePath.c_str());
- return;
- }
- // get search paths
- const char* envPaths = getenv("PATH");
- if (envPaths == nullptr)
- envPaths = "?";
- size_t envlen = strlen(envPaths);
- char* paths = new char[envlen + 1];
- strcpy(paths, envPaths);
- // find xdg-open (usually in /usr/bin)
- // Mac uses open instead
- #ifdef __APPLE__
- const char* fileOpen = "open";
- #else
- const char* fileOpen = "xdg-open";
- #endif
- string searchPath;
- char* searchDir = strtok(paths, ":");
- while (searchDir != nullptr)
- {
- searchPath = searchDir;
- if (searchPath.length() > 0
- && searchPath[searchPath.length() - 1] != g_fileSeparator)
- searchPath.append(string(1, g_fileSeparator));
- searchPath.append(fileOpen);
- if (stat(searchPath.c_str(), &statbuf) == 0 && (statbuf.st_mode & S_IFREG))
- break;
- searchDir = strtok(nullptr, ":");
- }
- delete[] paths;
- if (searchDir == nullptr)
- error(_("Command is not installed"), fileOpen);
- // browser open will be bypassed in test programs
- printf(_("Opening HTML documentation %s\n"), htmlFilePath.c_str());
- if (!bypassBrowserOpen)
- {
- execlp(fileOpen, fileOpen, htmlFilePath.c_str(), nullptr);
- // execlp will NOT return if successful
- error(_("Command execute failure"), fileOpen);
- }
- }
- #endif // _WIN32
- // get individual file names from the command-line file path
- void ASConsole::getFilePaths(const string& filePath)
- {
- fileName.clear();
- targetDirectory = string();
- targetFilename = string();
- // separate directory and file name
- size_t separator = filePath.find_last_of(g_fileSeparator);
- if (separator == string::npos)
- {
- // if no directory is present, use the currently active directory
- targetDirectory = getCurrentDirectory(filePath);
- targetFilename = filePath;
- mainDirectoryLength = targetDirectory.length() + 1; // +1 includes trailing separator
- }
- else
- {
- targetDirectory = filePath.substr(0, separator);
- targetFilename = filePath.substr(separator + 1);
- mainDirectoryLength = targetDirectory.length() + 1; // +1 includes trailing separator
- }
- if (targetFilename.length() == 0)
- {
- fprintf(stderr, _("Missing filename in %s\n"), filePath.c_str());
- error();
- }
- // check filename for wildcards
- hasWildcard = false;
- if (targetFilename.find_first_of("*?") != string::npos)
- hasWildcard = true;
- // clear exclude hits vector
- size_t excludeHitsVectorSize = excludeHitsVector.size();
- for (size_t ix = 0; ix < excludeHitsVectorSize; ix++)
- excludeHitsVector[ix] = false;
- // If the filename is not quoted on Linux, bash will replace the
- // wildcard instead of passing it to the program.
- if (isRecursive && !hasWildcard)
- {
- fprintf(stderr, "%s\n", _("Recursive option with no wildcard"));
- #ifndef _WIN32
- fprintf(stderr, "%s\n", _("Did you intend quote the filename"));
- #endif
- error();
- }
- // display directory name for wildcard processing
- if (hasWildcard)
- {
- printSeparatingLine();
- printMsg(_("Directory %s\n"), targetDirectory + g_fileSeparator + targetFilename);
- }
- // create a vector of paths and file names to process
- if (hasWildcard || isRecursive)
- getFileNames(targetDirectory, targetFilename);
- else
- {
- // verify a single file is not a directory (needed on Linux)
- string entryFilepath = targetDirectory + g_fileSeparator + targetFilename;
- struct stat statbuf;
- if (stat(entryFilepath.c_str(), &statbuf) == 0 && (statbuf.st_mode & S_IFREG))
- fileName.emplace_back(entryFilepath);
- }
- // check for unprocessed excludes
- bool excludeErr = false;
- for (size_t ix = 0; ix < excludeHitsVector.size(); ix++)
- {
- if (!excludeHitsVector[ix])
- {
- excludeErr = true;
- if (!ignoreExcludeErrorsDisplay)
- {
- if (ignoreExcludeErrors)
- printMsg(_("Exclude (unmatched) %s\n"), excludeVector[ix]);
- else
- fprintf(stderr, _("Exclude (unmatched) %s\n"), excludeVector[ix].c_str());
- }
- else
- {
- if (!ignoreExcludeErrors)
- fprintf(stderr, _("Exclude (unmatched) %s\n"), excludeVector[ix].c_str());
- }
- }
- }
- if (excludeErr && !ignoreExcludeErrors)
- {
- if (hasWildcard && !isRecursive)
- fprintf(stderr, "%s\n", _("Did you intend to use --recursive"));
- error();
- }
- // check if files were found (probably an input error if not)
- if (fileName.empty())
- {
- fprintf(stderr, _("No file to process %s\n"), filePath.c_str());
- if (hasWildcard && !isRecursive)
- fprintf(stderr, "%s\n", _("Did you intend to use --recursive"));
- error();
- }
- if (hasWildcard)
- printSeparatingLine();
- }
- bool ASConsole::fileNameVectorIsEmpty() const
- {
- return fileNameVector.empty();
- }
- bool ASConsole::isOption(const string& arg, const char* op)
- {
- return arg.compare(op) == 0;
- }
- bool ASConsole::isOption(const string& arg, const char* a, const char* b)
- {
- return (isOption(arg, a) || isOption(arg, b));
- }
- bool ASConsole::isParamOption(const string& arg, const char* option)
- {
- bool retVal = arg.compare(0, strlen(option), option) == 0;
- // if comparing for short option, 2nd char of arg must be numeric
- if (retVal && strlen(option) == 1 && arg.length() > 1)
- if (!isdigit((unsigned char)arg[1]))
- retVal = false;
- return retVal;
- }
- // compare a path to the exclude vector
- // used for both directories and filenames
- // updates the g_excludeHitsVector
- // return true if a match
- bool ASConsole::isPathExclued(const string& subPath)
- {
- bool retVal = false;
- // read the exclude vector checking for a match
- for (size_t i = 0; i < excludeVector.size(); i++)
- {
- string exclude = excludeVector[i];
- if (subPath.length() < exclude.length())
- continue;
- size_t compareStart = subPath.length() - exclude.length();
- // subPath compare must start with a directory name
- if (compareStart > 0)
- {
- char lastPathChar = subPath[compareStart - 1];
- if (lastPathChar != g_fileSeparator)
- continue;
- }
- string compare = subPath.substr(compareStart);
- if (!g_isCaseSensitive)
- {
- // make it case insensitive for Windows
- for (size_t j = 0; j < compare.length(); j++)
- compare[j] = (char)tolower(compare[j]);
- for (size_t j = 0; j < exclude.length(); j++)
- exclude[j] = (char)tolower(exclude[j]);
- }
- // compare sub directory to exclude data - must check them all
- if (compare == exclude)
- {
- excludeHitsVector[i] = true;
- retVal = true;
- break;
- }
- }
- return retVal;
- }
- void ASConsole::printHelp() const
- {
- cout << endl;
- cout << " Artistic Style " << g_version << endl;
- cout << " Maintained by: Jim Pattee\n";
- cout << " Original Author: Tal Davidson\n";
- cout << endl;
- cout << "Usage:\n";
- cout << "------\n";
- cout << " astyle [OPTIONS] File1 File2 File3 [...]\n";
- cout << endl;
- cout << " astyle [OPTIONS] < Original > Beautified\n";
- cout << endl;
- cout << " When indenting a specific file, the resulting indented file RETAINS\n";
- cout << " the original file-name. The original pre-indented file is renamed,\n";
- cout << " with a suffix of \'.orig\' added to the original filename.\n";
- cout << endl;
- cout << " Wildcards (* and ?) may be used in the filename.\n";
- cout << " A \'recursive\' option can process directories recursively.\n";
- cout << endl;
- cout << " By default, astyle is set up to indent with four spaces per indent,\n";
- cout << " a maximal indentation of 40 spaces inside continuous statements,\n";
- cout << " a minimum indentation of eight spaces inside conditional statements,\n";
- cout << " and NO formatting options.\n";
- cout << endl;
- cout << "Options:\n";
- cout << "--------\n";
- cout << " This program follows the usual GNU command line syntax.\n";
- cout << " Long options (starting with '--') must be written one at a time.\n";
- cout << " Short options (starting with '-') may be appended together.\n";
- cout << " Thus, -bps4 is the same as -b -p -s4.\n";
- cout << endl;
- cout << "Options File:\n";
- cout << "-------------\n";
- cout << " Artistic Style looks for a default options file in the\n";
- cout << " following order:\n";
- cout << " 1. The contents of the ARTISTIC_STYLE_OPTIONS environment\n";
- cout << " variable if it exists.\n";
- cout << " 2. The file called .astylerc in the directory pointed to by the\n";
- cout << " HOME environment variable ( i.e. $HOME/.astylerc ).\n";
- cout << " 3. The file called astylerc in the directory pointed to by the\n";
- cout << " USERPROFILE environment variable (i.e. %USERPROFILE%\\astylerc).\n";
- cout << " If a default options file is found, the options in this file will\n";
- cout << " be parsed BEFORE the command-line options.\n";
- cout << " Long options within the default option file may be written without\n";
- cout << " the preliminary '--'.\n";
- cout << endl;
- cout << "Disable Formatting:\n";
- cout << "-------------------\n";
- cout << " Disable Block\n";
- cout << " Blocks of code can be disabled with the comment tags *INDENT-OFF*\n";
- cout << " and *INDENT-ON*. It must be contained in a one-line comment.\n";
- cout << endl;
- cout << " Disable Line\n";
- cout << " Padding of operators can be disabled on a single line using the\n";
- cout << " comment tag *NOPAD*. It must be contained in a line-end comment.\n";
- cout << endl;
- cout << "Brace Style Options:\n";
- cout << "--------------------\n";
- cout << " default brace style\n";
- cout << " If no brace style is requested, the opening braces will not be\n";
- cout << " changed and closing braces will be broken from the preceding line.\n";
- cout << endl;
- cout << " --style=allman OR --style=bsd OR --style=break OR -A1\n";
- cout << " Allman style formatting/indenting.\n";
- cout << " Broken braces.\n";
- cout << endl;
- cout << " --style=java OR --style=attach OR -A2\n";
- cout << " Java style formatting/indenting.\n";
- cout << " Attached braces.\n";
- cout << endl;
- cout << " --style=kr OR --style=k&r OR --style=k/r OR -A3\n";
- cout << " Kernighan & Ritchie style formatting/indenting.\n";
- cout << " Linux braces.\n";
- cout << endl;
- cout << " --style=stroustrup OR -A4\n";
- cout << " Stroustrup style formatting/indenting.\n";
- cout << " Linux braces.\n";
- cout << endl;
- cout << " --style=whitesmith OR -A5\n";
- cout << " Whitesmith style formatting/indenting.\n";
- cout << " Broken, indented braces.\n";
- cout << " Indented class blocks and switch blocks.\n";
- cout << endl;
- cout << " --style=vtk OR -A15\n";
- cout << " VTK style formatting/indenting.\n";
- cout << " Broken, indented braces except for the opening braces.\n";
- cout << endl;
- cout << " --style=banner OR -A6\n";
- cout << " Banner style formatting/indenting.\n";
- cout << " Attached, indented braces.\n";
- cout << endl;
- cout << " --style=gnu OR -A7\n";
- cout << " GNU style formatting/indenting.\n";
- cout << " Broken braces, indented blocks.\n";
- cout << endl;
- cout << " --style=linux OR --style=knf OR -A8\n";
- cout << " Linux style formatting/indenting.\n";
- cout << " Linux braces, minimum conditional indent is one-half indent.\n";
- cout << endl;
- cout << " --style=horstmann OR --style=run-in OR -A9\n";
- cout << " Horstmann style formatting/indenting.\n";
- cout << " Run-in braces, indented switches.\n";
- cout << endl;
- cout << " --style=1tbs OR --style=otbs OR -A10\n";
- cout << " One True Brace Style formatting/indenting.\n";
- cout << " Linux braces, add braces to all conditionals.\n";
- cout << endl;
- cout << " --style=google OR -A14\n";
- cout << " Google style formatting/indenting.\n";
- cout << " Attached braces, indented class modifiers.\n";
- cout << endl;
- cout << " --style=mozilla OR -A16\n";
- cout << " Mozilla style formatting/indenting.\n";
- cout << " Linux braces, with broken braces for structs and enums,\n";
- cout << " and attached braces for namespaces.\n";
- cout << endl;
- cout << " --style=pico OR -A11\n";
- cout << " Pico style formatting/indenting.\n";
- cout << " Run-in opening braces and attached closing braces.\n";
- cout << " Uses keep one line blocks and keep one line statements.\n";
- cout << endl;
- cout << " --style=lisp OR -A12\n";
- cout << " Lisp style formatting/indenting.\n";
- cout << " Attached opening braces and attached closing braces.\n";
- cout << " Uses keep one line statements.\n";
- cout << endl;
- cout << "Tab Options:\n";
- cout << "------------\n";
- cout << " default indent option\n";
- cout << " If no indentation option is set, the default\n";
- cout << " option of 4 spaces per indent will be used.\n";
- cout << endl;
- cout << " --indent=spaces=# OR -s#\n";
- cout << " Indent using # spaces per indent. Not specifying #\n";
- cout << " will result in a default of 4 spaces per indent.\n";
- cout << endl;
- cout << " --indent=tab OR --indent=tab=# OR -t OR -t#\n";
- cout << " Indent using tab characters, assuming that each\n";
- cout << " indent is # spaces long. Not specifying # will result\n";
- cout << " in a default assumption of 4 spaces per indent.\n";
- cout << endl;
- cout << " --indent=force-tab=# OR -T#\n";
- cout << " Indent using tab characters, assuming that each\n";
- cout << " indent is # spaces long. Force tabs to be used in areas\n";
- cout << " AStyle would prefer to use spaces.\n";
- cout << endl;
- cout << " --indent=force-tab-x=# OR -xT#\n";
- cout << " Allows the tab length to be set to a length that is different\n";
- cout << " from the indent length. This may cause the indentation to be\n";
- cout << " a mix of both spaces and tabs. This option sets the tab length.\n";
- cout << endl;
- cout << "Brace Modify Options:\n";
- cout << "---------------------\n";
- cout << " --attach-namespaces OR -xn\n";
- cout << " Attach braces to a namespace statement.\n";
- cout << endl;
- cout << " --attach-classes OR -xc\n";
- cout << " Attach braces to a class statement.\n";
- cout << endl;
- cout << " --attach-inlines OR -xl\n";
- cout << " Attach braces to class inline function definitions.\n";
- cout << endl;
- cout << " --attach-extern-c OR -xk\n";
- cout << " Attach braces to an extern \"C\" statement.\n";
- cout << endl;
- cout << " --attach-closing-while OR -xV\n";
- cout << " Attach closing while of do-while to the closing brace.\n";
- cout << endl;
- cout << "Indentation Options:\n";
- cout << "--------------------\n";
- cout << " --indent-classes OR -C\n";
- cout << " Indent 'class' blocks so that the entire block is indented.\n";
- cout << endl;
- cout << " --indent-modifiers OR -xG\n";
- cout << " Indent 'class' access modifiers, 'public:', 'protected:' or\n";
- cout << " 'private:', one half indent. The rest of the class is not\n";
- cout << " indented. \n";
- cout << endl;
- cout << " --indent-switches OR -S\n";
- cout << " Indent 'switch' blocks, so that the inner 'case XXX:'\n";
- cout << " headers are indented in relation to the switch block.\n";
- cout << endl;
- cout << " --indent-cases OR -K\n";
- cout << " Indent case blocks from the 'case XXX:' headers.\n";
- cout << " Case statements not enclosed in blocks are NOT indented.\n";
- cout << endl;
- cout << " --indent-namespaces OR -N\n";
- cout << " Indent the contents of namespace blocks.\n";
- cout << endl;
- cout << " --indent-after-parens OR -xU\n";
- cout << " Indent, instead of align, continuation lines following lines\n";
- cout << " that contain an opening paren '(' or an assignment '='. \n";
- cout << endl;
- cout << " --indent-continuation=# OR -xt#\n";
- cout << " Indent continuation lines an additional # indents.\n";
- cout << " The valid values are 0 thru 4 indents.\n";
- cout << " The default value is 1 indent.\n";
- cout << endl;
- cout << " --indent-labels OR -L\n";
- cout << " Indent labels so that they appear one indent less than\n";
- cout << " the current indentation level, rather than being\n";
- cout << " flushed completely to the left (which is the default).\n";
- cout << endl;
- cout << " --indent-preproc-block OR -xW\n";
- cout << " Indent preprocessor blocks at brace level 0.\n";
- cout << " Without this option the preprocessor block is not indented.\n";
- cout << endl;
- cout << " --indent-preproc-cond OR -xw\n";
- cout << " Indent preprocessor conditional statements #if/#else/#endif\n";
- cout << " to the same level as the source code.\n";
- cout << endl;
- cout << " --indent-preproc-define OR -w\n";
- cout << " Indent multi-line preprocessor #define statements.\n";
- cout << endl;
- cout << " --indent-col1-comments OR -Y\n";
- cout << " Indent line comments that start in column one.\n";
- cout << endl;
- cout << " --min-conditional-indent=# OR -m#\n";
- cout << " Indent a minimal # spaces in a continuous conditional\n";
- cout << " belonging to a conditional header.\n";
- cout << " The valid values are:\n";
- cout << " 0 - no minimal indent.\n";
- cout << " 1 - indent at least one additional indent.\n";
- cout << " 2 - indent at least two additional indents.\n";
- cout << " 3 - indent at least one-half an additional indent.\n";
- cout << " The default value is 2, two additional indents.\n";
- cout << endl;
- cout << " --max-continuation-indent=# OR -M#\n";
- cout << " Indent a maximal # spaces in a continuation line,\n";
- cout << " relative to the previous line.\n";
- cout << " The valid values are 40 thru 120.\n";
- cout << " The default value is 40.\n";
- cout << endl;
- cout << "Padding Options:\n";
- cout << "----------------\n";
- cout << " --break-blocks OR -f\n";
- cout << " Insert empty lines around unrelated blocks, labels, classes, ...\n";
- cout << endl;
- cout << " --break-blocks=all OR -F\n";
- cout << " Like --break-blocks, except also insert empty lines \n";
- cout << " around closing headers (e.g. 'else', 'catch', ...).\n";
- cout << endl;
- cout << " --pad-oper OR -p\n";
- cout << " Insert space padding around operators.\n";
- cout << endl;
- cout << " --pad-comma OR -xg\n";
- cout << " Insert space padding after commas.\n";
- cout << endl;
- cout << " --pad-paren OR -P\n";
- cout << " Insert space padding around parenthesis on both the outside\n";
- cout << " and the inside.\n";
- cout << endl;
- cout << " --pad-paren-out OR -d\n";
- cout << " Insert space padding around parenthesis on the outside only.\n";
- cout << endl;
- cout << " --pad-first-paren-out OR -xd\n";
- cout << " Insert space padding around first parenthesis in a series on\n";
- cout << " the outside only.\n";
- cout << endl;
- cout << " --pad-paren-in OR -D\n";
- cout << " Insert space padding around parenthesis on the inside only.\n";
- cout << endl;
- cout << " --pad-header OR -H\n";
- cout << " Insert space padding after paren headers (e.g. 'if', 'for'...).\n";
- cout << endl;
- cout << " --unpad-paren OR -U\n";
- cout << " Remove unnecessary space padding around parenthesis. This\n";
- cout << " can be used in combination with the 'pad' options above.\n";
- cout << endl;
- cout << " --delete-empty-lines OR -xd\n";
- cout << " Delete empty lines within a function or method.\n";
- cout << " It will NOT delete lines added by the break-blocks options.\n";
- cout << endl;
- cout << " --fill-empty-lines OR -E\n";
- cout << " Fill empty lines with the white space of their\n";
- cout << " previous lines.\n";
- cout << endl;
- cout << " --align-pointer=type OR -k1\n";
- cout << " --align-pointer=middle OR -k2\n";
- cout << " --align-pointer=name OR -k3\n";
- cout << " Attach a pointer or reference operator (*, &, or ^) to either\n";
- cout << " the operator type (left), middle, or operator name (right).\n";
- cout << " To align the reference separately use --align-reference.\n";
- cout << endl;
- cout << " --align-reference=none OR -W0\n";
- cout << " --align-reference=type OR -W1\n";
- cout << " --align-reference=middle OR -W2\n";
- cout << " --align-reference=name OR -W3\n";
- cout << " Attach a reference operator (&) to either\n";
- cout << " the operator type (left), middle, or operator name (right).\n";
- cout << " If not set, follow pointer alignment.\n";
- cout << endl;
- cout << "Formatting Options:\n";
- cout << "-------------------\n";
- cout << " --break-closing-braces OR -y\n";
- cout << " Break braces before closing headers (e.g. 'else', 'catch', ...).\n";
- cout << " Use with --style=java, --style=kr, --style=stroustrup,\n";
- cout << " --style=linux, or --style=1tbs.\n";
- cout << endl;
- cout << " --break-elseifs OR -e\n";
- cout << " Break 'else if()' statements into two different lines.\n";
- cout << endl;
- cout << " --break-one-line-headers OR -xb\n";
- cout << " Break one line headers (e.g. 'if', 'while', 'else', ...) from a\n";
- cout << " statement residing on the same line.\n";
- cout << endl;
- cout << " --add-braces OR -j\n";
- cout << " Add braces to unbraced one line conditional statements.\n";
- cout << endl;
- cout << " --add-one-line-braces OR -J\n";
- cout << " Add one line braces to unbraced one line conditional\n";
- cout << " statements.\n";
- cout << endl;
- cout << " --remove-braces OR -xj\n";
- cout << " Remove braces from a braced one line conditional statements.\n";
- cout << endl;
- cout << " --keep-one-line-blocks OR -O\n";
- cout << " Don't break blocks residing completely on one line.\n";
- cout << endl;
- cout << " --keep-one-line-statements OR -o\n";
- cout << " Don't break lines containing multiple statements into\n";
- cout << " multiple single-statement lines.\n";
- cout << endl;
- cout << " --convert-tabs OR -c\n";
- cout << " Convert tabs to the appropriate number of spaces.\n";
- cout << endl;
- cout << " --close-templates OR -xy\n";
- cout << " Close ending angle brackets on template definitions.\n";
- cout << endl;
- cout << " --remove-comment-prefix OR -xp\n";
- cout << " Remove the leading '*' prefix on multi-line comments and\n";
- cout << " indent the comment text one indent.\n";
- cout << endl;
- cout << " --max-code-length=# OR -xC#\n";
- cout << " --break-after-logical OR -xL\n";
- cout << " max-code-length=# will break the line if it exceeds more than\n";
- cout << " # characters. The valid values are 50 thru 200.\n";
- cout << " If the line contains logical conditionals they will be placed\n";
- cout << " first on the new line. The option break-after-logical will\n";
- cout << " cause the logical conditional to be placed last on the\n";
- cout << " previous line.\n";
- cout << endl;
- cout << " --mode=c\n";
- cout << " Indent a C or C++ source file (this is the default).\n";
- cout << endl;
- cout << " --mode=java\n";
- cout << " Indent a Java source file.\n";
- cout << endl;
- cout << " --mode=cs\n";
- cout << " Indent a C# source file.\n";
- cout << endl;
- cout << "Objective-C Options:\n";
- cout << "--------------------\n";
- cout << " --pad-method-prefix OR -xQ\n";
- cout << " Insert space padding after the '-' or '+' Objective-C\n";
- cout << " method prefix.\n";
- cout << endl;
- cout << " --unpad-method-prefix OR -xR\n";
- cout << " Remove all space padding after the '-' or '+' Objective-C\n";
- cout << " method prefix.\n";
- cout << endl;
- cout << " --pad-return-type OR -xq\n";
- cout << " Insert space padding after the Objective-C return type.\n";
- cout << endl;
- cout << " --unpad-return-type OR -xr\n";
- cout << " Remove all space padding after the Objective-C return type.\n";
- cout << endl;
- cout << " --pad-param-type OR -xS\n";
- cout << " Insert space padding after the Objective-C return type.\n";
- cout << endl;
- cout << " --unpad-param-type OR -xs\n";
- cout << " Remove all space padding after the Objective-C return type.\n";
- cout << endl;
- cout << " --align-method-colon OR -xM\n";
- cout << " Align the colons in an Objective-C method definition.\n";
- cout << endl;
- cout << " --pad-method-colon=none OR -xP\n";
- cout << " --pad-method-colon=all OR -xP1\n";
- cout << " --pad-method-colon=after OR -xP2\n";
- cout << " --pad-method-colon=before OR -xP3\n";
- cout << " Add or remove space padding before or after the colons in an\n";
- cout << " Objective-C method call.\n";
- cout << endl;
- cout << "Other Options:\n";
- cout << "--------------\n";
- cout << " --suffix=####\n";
- cout << " Append the suffix #### instead of '.orig' to original filename.\n";
- cout << endl;
- cout << " --suffix=none OR -n\n";
- cout << " Do not retain a backup of the original file.\n";
- cout << endl;
- cout << " --recursive OR -r OR -R\n";
- cout << " Process subdirectories recursively.\n";
- cout << endl;
- cout << " --dry-run\n";
- cout << " Perform a trial run with no changes made to check for formatting.\n";
- cout << endl;
- cout << " --exclude=####\n";
- cout << " Specify a file or directory #### to be excluded from processing.\n";
- cout << endl;
- cout << " --ignore-exclude-errors OR -i\n";
- cout << " Allow processing to continue if there are errors in the exclude=####\n";
- cout << " options. It will display the unmatched excludes.\n";
- cout << endl;
- cout << " --ignore-exclude-errors-x OR -xi\n";
- cout << " Allow processing to continue if there are errors in the exclude=####\n";
- cout << " options. It will NOT display the unmatched excludes.\n";
- cout << endl;
- cout << " --errors-to-stdout OR -X\n";
- cout << " Print errors and help information to standard-output rather than\n";
- cout << " to standard-error.\n";
- cout << endl;
- cout << " --preserve-date OR -Z\n";
- cout << " Preserve the original file's date and time modified. The time\n";
- cout << " modified will be changed a few micro seconds to force a compile.\n";
- cout << endl;
- cout << " --verbose OR -v\n";
- cout << " Verbose mode. Extra informational messages will be displayed.\n";
- cout << endl;
- cout << " --formatted OR -Q\n";
- cout << " Formatted display mode. Display only the files that have been\n";
- cout << " formatted.\n";
- cout << endl;
- cout << " --quiet OR -q\n";
- cout << " Quiet mode. Suppress all output except error messages.\n";
- cout << endl;
- cout << " --lineend=windows OR -z1\n";
- cout << " --lineend=linux OR -z2\n";
- cout << " --lineend=macold OR -z3\n";
- cout << " Force use of the specified line end style. Valid options\n";
- cout << " are windows (CRLF), linux (LF), and macold (CR).\n";
- cout << endl;
- cout << "Command Line Only:\n";
- cout << "------------------\n";
- cout << " --options=####\n";
- cout << " Specify an options file #### to read and use.\n";
- cout << endl;
- cout << " --options=none\n";
- cout << " Disable the default options file.\n";
- cout << " Only the command-line parameters will be used.\n";
- cout << endl;
- cout << " --ascii OR -I\n";
- cout << " The displayed output will be ascii characters only.\n";
- cout << endl;
- cout << " --version OR -V\n";
- cout << " Print version number.\n";
- cout << endl;
- cout << " --help OR -h OR -?\n";
- cout << " Print this help message.\n";
- cout << endl;
- cout << " --html OR -!\n";
- cout << " Open the HTML help file \"astyle.html\" in the default browser.\n";
- cout << " The documentation must be installed in the standard install path.\n";
- cout << endl;
- cout << " --html=####\n";
- cout << " Open a HTML help file in the default browser using the file path\n";
- cout << " ####. The path may include a directory path and a file name, or a\n";
- cout << " file name only. Paths containing spaces must be enclosed in quotes.\n";
- cout << endl;
- cout << endl;
- }
- /**
- * Process files in the fileNameVector.
- */
- void ASConsole::processFiles()
- {
- if (isVerbose)
- printVerboseHeader();
- clock_t startTime = clock(); // start time of file formatting
- // loop thru input fileNameVector and process the files
- for (size_t i = 0; i < fileNameVector.size(); i++)
- {
- getFilePaths(fileNameVector[i]);
- // loop thru fileName vector formatting the files
- for (size_t j = 0; j < fileName.size(); j++)
- formatFile(fileName[j]);
- }
- // files are processed, display stats
- if (isVerbose)
- printVerboseStats(startTime);
- }
- // process options from the command line and options file
- // build the vectors fileNameVector, excludeVector, optionsVector, and fileOptionsVector
- void ASConsole::processOptions(const vector<string>& argvOptions)
- {
- string arg;
- bool ok = true;
- bool shouldParseOptionsFile = true;
- // get command line options
- for (size_t i = 0; i < argvOptions.size(); i++)
- {
- arg = argvOptions[i];
- if ( isOption(arg, "-I" )
- || isOption(arg, "--ascii") )
- {
- useAscii = true;
- setlocale(LC_ALL, "C"); // use English decimal indicator
- localizer.setLanguageFromName("en");
- }
- else if ( isOption(arg, "--options=none") )
- {
- shouldParseOptionsFile = false;
- }
- else if ( isParamOption(arg, "--options=") )
- {
- optionsFileName = getParam(arg, "--options=");
- optionsFileRequired = true;
- if (optionsFileName.empty())
- setOptionsFileName(" ");
- }
- else if ( isOption(arg, "-h")
- || isOption(arg, "--help")
- || isOption(arg, "-?") )
- {
- printHelp();
- exit(EXIT_SUCCESS);
- }
- else if ( isOption(arg, "-!")
- || isOption(arg, "--html") )
- {
- launchDefaultBrowser();
- exit(EXIT_SUCCESS);
- }
- else if ( isParamOption(arg, "--html=") )
- {
- string htmlFilePath = getParam(arg, "--html=");
- launchDefaultBrowser(htmlFilePath.c_str());
- exit(EXIT_SUCCESS);
- }
- else if ( isOption(arg, "-V" )
- || isOption(arg, "--version") )
- {
- printf("Artistic Style Version %s\n", g_version);
- exit(EXIT_SUCCESS);
- }
- else if (arg[0] == '-')
- {
- optionsVector.emplace_back(arg);
- }
- else // file-name
- {
- standardizePath(arg);
- fileNameVector.emplace_back(arg);
- }
- }
- // get options file path and name
- if (shouldParseOptionsFile)
- {
- if (optionsFileName.empty())
- {
- char* env = getenv("ARTISTIC_STYLE_OPTIONS");
- if (env != nullptr)
- setOptionsFileName(env);
- }
- if (optionsFileName.empty())
- {
- char* env = getenv("HOME");
- if (env != nullptr)
- setOptionsFileName(string(env) + "/.astylerc");
- }
- if (optionsFileName.empty())
- {
- char* env = getenv("USERPROFILE");
- if (env != nullptr)
- setOptionsFileName(string(env) + "/astylerc");
- }
- if (!optionsFileName.empty())
- standardizePath(optionsFileName);
- }
- // create the options file vector and parse the options for errors
- ASOptions options(formatter, *this);
- if (!optionsFileName.empty())
- {
- ifstream optionsIn(optionsFileName.c_str());
- if (optionsIn)
- {
- options.importOptions(optionsIn, fileOptionsVector);
- ok = options.parseOptions(fileOptionsVector,
- string(_("Invalid option file options:")));
- }
- else
- {
- if (optionsFileRequired)
- error(_("Cannot open options file"), optionsFileName.c_str());
- optionsFileName.clear();
- }
- optionsIn.close();
- }
- if (!ok)
- {
- (*errorStream) << options.getOptionErrors() << endl;
- (*errorStream) << _("For help on options type 'astyle -h'") << endl;
- error();
- }
- // parse the command line options vector for errors
- ok = options.parseOptions(optionsVector,
- string(_("Invalid command line options:")));
- if (!ok)
- {
- (*errorStream) << options.getOptionErrors() << endl;
- (*errorStream) << _("For help on options type 'astyle -h'") << endl;
- error();
- }
- }
- // remove a file and check for an error
- void ASConsole::removeFile(const char* fileName_, const char* errMsg) const
- {
- if (remove(fileName_) != 0)
- {
- if (errno == ENOENT) // no file is OK
- errno = 0;
- if (errno)
- {
- perror("errno message");
- error(errMsg, fileName_);
- }
- }
- }
- // rename a file and check for an error
- void ASConsole::renameFile(const char* oldFileName, const char* newFileName, const char* errMsg) const
- {
- int result = rename(oldFileName, newFileName);
- if (result != 0)
- {
- // if file still exists the remove needs more time - retry
- if (errno == EEXIST)
- {
- errno = 0;
- waitForRemove(newFileName);
- result = rename(oldFileName, newFileName);
- }
- if (result != 0)
- {
- perror("errno message");
- error(errMsg, oldFileName);
- }
- }
- }
- // make sure file separators are correct type (Windows or Linux)
- // remove ending file separator
- // remove beginning file separator if requested and NOT a complete file path
- void ASConsole::standardizePath(string& path, bool removeBeginningSeparator /*false*/) const
- {
- #ifdef __VMS
- struct FAB fab;
- struct NAML naml;
- char less[NAML$C_MAXRSS];
- char sess[NAM$C_MAXRSS];
- int r0_status;
- // If we are on a VMS system, translate VMS style filenames to unix
- // style.
- fab = cc$rms_fab;
- fab.fab$l_fna = (char*) -1; // *NOPAD*
- fab.fab$b_fns = 0;
- fab.fab$l_naml = &naml;
- naml = cc$rms_naml;
- strcpy(sess, path.c_str());
- naml.naml$l_long_filename = (char*)sess;
- naml.naml$l_long_filename_size = path.length();
- naml.naml$l_long_expand = less;
- naml.naml$l_long_expand_alloc = sizeof(less);
- naml.naml$l_esa = sess;
- naml.naml$b_ess = sizeof(sess);
- naml.naml$v_no_short_upcase = 1;
- r0_status = sys$parse(&fab);
- if (r0_status == RMS$_SYN)
- {
- error("File syntax error", path.c_str());
- }
- else
- {
- if (!$VMS_STATUS_SUCCESS(r0_status))
- {
- (void)lib$signal (r0_status);
- }
- }
- less[naml.naml$l_long_expand_size - naml.naml$b_ver] = '\0';
- sess[naml.naml$b_esl - naml.naml$b_ver] = '\0';
- if (naml.naml$l_long_expand_size > naml.naml$b_esl)
- {
- path = decc$translate_vms (less);
- }
- else
- {
- path = decc$translate_vms(sess);
- }
- #endif /* __VMS */
- // make sure separators are correct type (Windows or Linux)
- for (size_t i = 0; i < path.length(); i++)
- {
- i = path.find_first_of("/\\", i);
- if (i == string::npos)
- break;
- path[i] = g_fileSeparator;
- }
- // remove beginning separator if requested
- if (removeBeginningSeparator && (path[0] == g_fileSeparator))
- path.erase(0, 1);
- }
- void ASConsole::printMsg(const char* msg, const string& data) const
- {
- if (isQuiet)
- return;
- printf(msg, data.c_str());
- }
- void ASConsole::printSeparatingLine() const
- {
- string line;
- for (size_t i = 0; i < 60; i++)
- line.append("-");
- printMsg("%s\n", line);
- }
- void ASConsole::printVerboseHeader() const
- {
- assert(isVerbose);
- if (isQuiet)
- return;
- // get the date
- time_t lt;
- char str[20];
- lt = time(nullptr);
- struct tm* ptr = localtime(<);
- strftime(str, 20, "%x", ptr);
- // print the header
- // 60 is the length of the separator in printSeparatingLine()
- string header = "Artistic Style " + string(g_version);
- size_t numSpaces = 60 - header.length() - strlen(str);
- header.append(numSpaces, ' ');
- header.append(str);
- header.append("\n");
- printf("%s", header.c_str());
- // print options file
- if (!optionsFileName.empty())
- printf(_("Using default options file %s\n"), optionsFileName.c_str());
- }
- void ASConsole::printVerboseStats(clock_t startTime) const
- {
- assert(isVerbose);
- if (isQuiet)
- return;
- if (hasWildcard)
- printSeparatingLine();
- string formatted = getNumberFormat(filesFormatted);
- string unchanged = getNumberFormat(filesUnchanged);
- printf(_(" %s formatted %s unchanged "), formatted.c_str(), unchanged.c_str());
- // show processing time
- clock_t stopTime = clock();
- double secs = (stopTime - startTime) / double (CLOCKS_PER_SEC);
- if (secs < 60)
- {
- if (secs < 2.0)
- printf("%.2f", secs);
- else if (secs < 20.0)
- printf("%.1f", secs);
- else
- printf("%.0f", secs);
- printf("%s", _(" seconds "));
- }
- else
- {
- // show minutes and seconds if time is greater than one minute
- int min = (int) secs / 60;
- secs -= min * 60;
- int minsec = int (secs + .5);
- printf(_("%d min %d sec "), min, minsec);
- }
- string lines = getNumberFormat(linesOut);
- printf(_("%s lines\n"), lines.c_str());
- }
- void ASConsole::sleep(int seconds) const
- {
- clock_t endwait;
- endwait = clock_t (clock () + seconds * CLOCKS_PER_SEC);
- while (clock() < endwait) {}
- }
- bool ASConsole::stringEndsWith(const string& str, const string& suffix) const
- {
- int strIndex = (int) str.length() - 1;
- int suffixIndex = (int) suffix.length() - 1;
- while (strIndex >= 0 && suffixIndex >= 0)
- {
- if (tolower(str[strIndex]) != tolower(suffix[suffixIndex]))
- return false;
- --strIndex;
- --suffixIndex;
- }
- // suffix longer than string
- if (strIndex < 0 && suffixIndex >= 0)
- return false;
- return true;
- }
- void ASConsole::updateExcludeVector(const string& suffixParam)
- {
- excludeVector.emplace_back(suffixParam);
- standardizePath(excludeVector.back(), true);
- excludeHitsVector.push_back(false);
- }
- int ASConsole::waitForRemove(const char* newFileName) const
- {
- struct stat stBuf;
- int seconds;
- // sleep a max of 20 seconds for the remove
- for (seconds = 1; seconds <= 20; seconds++)
- {
- sleep(1);
- if (stat(newFileName, &stBuf) != 0)
- break;
- }
- errno = 0;
- return seconds;
- }
- // From The Code Project http://www.codeproject.com/string/wildcmp.asp
- // Written by Jack Handy - jakkhandy@hotmail.com
- // Modified to compare case insensitive for Windows
- int ASConsole::wildcmp(const char* wild, const char* data) const
- {
- const char* cp = nullptr, *mp = nullptr;
- bool cmpval;
- while ((*data) && (*wild != '*'))
- {
- if (!g_isCaseSensitive)
- cmpval = (tolower(*wild) != tolower(*data)) && (*wild != '?');
- else
- cmpval = (*wild != *data) && (*wild != '?');
- if (cmpval)
- {
- return 0;
- }
- wild++;
- data++;
- }
- while (*data)
- {
- if (*wild == '*')
- {
- if (!*++wild)
- {
- return 1;
- }
- mp = wild;
- cp = data + 1;
- }
- else
- {
- if (!g_isCaseSensitive)
- cmpval = (tolower(*wild) == tolower(*data) || (*wild == '?'));
- else
- cmpval = (*wild == *data) || (*wild == '?');
- if (cmpval)
- {
- wild++;
- data++;
- }
- else
- {
- wild = mp;
- data = cp++;
- }
- }
- }
- while (*wild == '*')
- {
- wild++;
- }
- return !*wild;
- }
- void ASConsole::writeFile(const string& fileName_, FileEncoding encoding, ostringstream& out) const
- {
- // save date accessed and date modified of original file
- struct stat stBuf;
- bool statErr = false;
- if (stat(fileName_.c_str(), &stBuf) == -1)
- statErr = true;
- // create a backup
- if (!noBackup)
- {
- string origFileName = fileName_ + origSuffix;
- removeFile(origFileName.c_str(), "Cannot remove pre-existing backup file");
- renameFile(fileName_.c_str(), origFileName.c_str(), "Cannot create backup file");
- }
- // write the output file
- ofstream fout(fileName_.c_str(), ios::binary | ios::trunc);
- if (!fout)
- error("Cannot open output file", fileName_.c_str());
- if (encoding == UTF_16LE || encoding == UTF_16BE)
- {
- // convert utf-8 to utf-16
- bool isBigEndian = (encoding == UTF_16BE);
- size_t utf16Size = utf8_16.utf16LengthFromUtf8(out.str().c_str(), out.str().length());
- char* utf16Out = new char[utf16Size];
- size_t utf16Len = utf8_16.utf8ToUtf16(const_cast<char*>(out.str().c_str()),
- out.str().length(), isBigEndian, utf16Out);
- assert(utf16Len == utf16Size);
- fout << string(utf16Out, utf16Len);
- delete[] utf16Out;
- }
- else
- fout << out.str();
- fout.close();
- // change date modified to original file date
- // Embarcadero must be linked with cw32mt not cw32
- if (preserveDate)
- {
- if (!statErr)
- {
- struct utimbuf outBuf;
- outBuf.actime = stBuf.st_atime;
- // add ticks so 'make' will recognize a change
- // Visual Studio 2008 needs more than 1
- outBuf.modtime = stBuf.st_mtime + 10;
- if (utime(fileName_.c_str(), &outBuf) == -1)
- statErr = true;
- }
- if (statErr)
- {
- perror("errno message");
- (*errorStream) << "********* Cannot preserve file date" << endl;
- }
- }
- }
- #else // ASTYLE_LIB
- //-----------------------------------------------------------------------------
- // ASLibrary class
- // used by shared object (DLL) calls
- //-----------------------------------------------------------------------------
- utf16_t* ASLibrary::formatUtf16(const utf16_t* pSourceIn, // the source to be formatted
- const utf16_t* pOptions, // AStyle options
- fpError fpErrorHandler, // error handler function
- fpAlloc fpMemoryAlloc) const // memory allocation function)
- {
- const char* utf8In = convertUtf16ToUtf8(pSourceIn);
- if (utf8In == nullptr)
- {
- fpErrorHandler(121, "Cannot convert input utf-16 to utf-8.");
- return nullptr;
- }
- const char* utf8Options = convertUtf16ToUtf8(pOptions);
- if (utf8Options == nullptr)
- {
- delete[] utf8In;
- fpErrorHandler(122, "Cannot convert options utf-16 to utf-8.");
- return nullptr;
- }
- // call the Artistic Style formatting function
- // cannot use the callers memory allocation here
- char* utf8Out = AStyleMain(utf8In,
- utf8Options,
- fpErrorHandler,
- ASLibrary::tempMemoryAllocation);
- // finished with these
- delete[] utf8In;
- delete[] utf8Options;
- utf8In = nullptr;
- utf8Options = nullptr;
- // AStyle error has already been sent
- if (utf8Out == nullptr)
- return nullptr;
- // convert text to wide char and return it
- utf16_t* utf16Out = convertUtf8ToUtf16(utf8Out, fpMemoryAlloc);
- delete[] utf8Out;
- utf8Out = nullptr;
- if (utf16Out == nullptr)
- {
- fpErrorHandler(123, "Cannot convert output utf-8 to utf-16.");
- return nullptr;
- }
- return utf16Out;
- }
- // STATIC method to allocate temporary memory for AStyle formatting.
- // The data will be converted before being returned to the calling program.
- char* STDCALL ASLibrary::tempMemoryAllocation(unsigned long memoryNeeded)
- {
- char* buffer = new (nothrow) char[memoryNeeded];
- return buffer;
- }
- /**
- * Convert utf-8 strings to utf16 strings.
- * Memory is allocated by the calling program memory allocation function.
- * The calling function must check for errors.
- */
- utf16_t* ASLibrary::convertUtf8ToUtf16(const char* utf8In, fpAlloc fpMemoryAlloc) const
- {
- if (utf8In == nullptr)
- return nullptr;
- char* data = const_cast<char*>(utf8In);
- size_t dataSize = strlen(utf8In);
- bool isBigEndian = utf8_16.getBigEndian();
- // return size is in number of CHARs, not utf16_t
- size_t utf16Size = (utf8_16.utf16LengthFromUtf8(data, dataSize) + sizeof(utf16_t));
- char* utf16Out = fpMemoryAlloc((long)utf16Size);
- if (utf16Out == nullptr)
- return nullptr;
- #ifdef NDEBUG
- utf8_16.utf8ToUtf16(data, dataSize + 1, isBigEndian, utf16Out);
- #else
- size_t utf16Len = utf8_16.utf8ToUtf16(data, dataSize + 1, isBigEndian, utf16Out);
- assert(utf16Len == utf16Size);
- #endif
- assert(utf16Size == (utf8_16.utf16len(reinterpret_cast<utf16_t*>(utf16Out)) + 1) * sizeof(utf16_t));
- return reinterpret_cast<utf16_t*>(utf16Out);
- }
- /**
- * Convert utf16 strings to utf-8.
- * The calling function must check for errors and delete the
- * allocated memory.
- */
- char* ASLibrary::convertUtf16ToUtf8(const utf16_t* utf16In) const
- {
- if (utf16In == nullptr)
- return nullptr;
- char* data = reinterpret_cast<char*>(const_cast<utf16_t*>(utf16In));
- // size must be in chars
- size_t dataSize = utf8_16.utf16len(utf16In) * sizeof(utf16_t);
- bool isBigEndian = utf8_16.getBigEndian();
- size_t utf8Size = utf8_16.utf8LengthFromUtf16(data, dataSize, isBigEndian) + 1;
- char* utf8Out = new (nothrow) char[utf8Size];
- if (utf8Out == nullptr)
- return nullptr;
- #ifdef NDEBUG
- utf8_16.utf16ToUtf8(data, dataSize + 1, isBigEndian, true, utf8Out);
- #else
- size_t utf8Len = utf8_16.utf16ToUtf8(data, dataSize + 1, isBigEndian, true, utf8Out);
- assert(utf8Len == utf8Size);
- #endif
- assert(utf8Size == strlen(utf8Out) + 1);
- return utf8Out;
- }
- #endif // ASTYLE_LIB
- //-----------------------------------------------------------------------------
- // ASOptions class
- // used by both console and library builds
- //-----------------------------------------------------------------------------
- #ifdef ASTYLE_LIB
- ASOptions::ASOptions(ASFormatter& formatterArg)
- : formatter(formatterArg)
- { }
- #else
- ASOptions::ASOptions(ASFormatter& formatterArg, ASConsole& consoleArg)
- : formatter(formatterArg), console(consoleArg)
- { }
- #endif
- /**
- * parse the options vector
- * optionsVector can be either a fileOptionsVector (options file) or an optionsVector (command line)
- *
- * @return true if no errors, false if errors
- */
- bool ASOptions::parseOptions(vector<string>& optionsVector, const string& errorInfo)
- {
- vector<string>::iterator option;
- string arg, subArg;
- optionErrors.clear();
- for (option = optionsVector.begin(); option != optionsVector.end(); ++option)
- {
- arg = *option;
- if (arg.compare(0, 2, "--") == 0)
- parseOption(arg.substr(2), errorInfo);
- else if (arg[0] == '-')
- {
- size_t i;
- for (i = 1; i < arg.length(); ++i)
- {
- if (i > 1
- && isalpha((unsigned char)arg[i])
- && arg[i - 1] != 'x')
- {
- // parse the previous option in subArg
- parseOption(subArg, errorInfo);
- subArg = "";
- }
- // append the current option to subArg
- subArg.append(1, arg[i]);
- }
- // parse the last option
- parseOption(subArg, errorInfo);
- subArg = "";
- }
- else
- {
- parseOption(arg, errorInfo);
- subArg = "";
- }
- }
- if (optionErrors.str().length() > 0)
- return false;
- return true;
- }
- void ASOptions::parseOption(const string& arg, const string& errorInfo)
- {
- if ( isOption(arg, "style=allman") || isOption(arg, "style=bsd") || isOption(arg, "style=break") )
- {
- formatter.setFormattingStyle(STYLE_ALLMAN);
- }
- else if ( isOption(arg, "style=java") || isOption(arg, "style=attach") )
- {
- formatter.setFormattingStyle(STYLE_JAVA);
- }
- else if ( isOption(arg, "style=k&r") || isOption(arg, "style=kr") || isOption(arg, "style=k/r") )
- {
- formatter.setFormattingStyle(STYLE_KR);
- }
- else if ( isOption(arg, "style=stroustrup") )
- {
- formatter.setFormattingStyle(STYLE_STROUSTRUP);
- }
- else if ( isOption(arg, "style=whitesmith") )
- {
- formatter.setFormattingStyle(STYLE_WHITESMITH);
- }
- else if ( isOption(arg, "style=vtk") )
- {
- formatter.setFormattingStyle(STYLE_VTK);
- }
- else if ( isOption(arg, "style=banner") )
- {
- formatter.setFormattingStyle(STYLE_BANNER);
- }
- else if ( isOption(arg, "style=gnu") )
- {
- formatter.setFormattingStyle(STYLE_GNU);
- }
- else if ( isOption(arg, "style=linux") || isOption(arg, "style=knf") )
- {
- formatter.setFormattingStyle(STYLE_LINUX);
- }
- else if ( isOption(arg, "style=horstmann") || isOption(arg, "style=run-in") )
- {
- formatter.setFormattingStyle(STYLE_HORSTMANN);
- }
- else if ( isOption(arg, "style=1tbs") || isOption(arg, "style=otbs") )
- {
- formatter.setFormattingStyle(STYLE_1TBS);
- }
- else if ( isOption(arg, "style=google") )
- {
- formatter.setFormattingStyle(STYLE_GOOGLE);
- }
- else if (isOption(arg, "style=mozilla"))
- {
- formatter.setFormattingStyle(STYLE_MOZILLA);
- }
- else if ( isOption(arg, "style=pico") )
- {
- formatter.setFormattingStyle(STYLE_PICO);
- }
- else if ( isOption(arg, "style=lisp") || isOption(arg, "style=python") )
- {
- formatter.setFormattingStyle(STYLE_LISP);
- }
- else if ( isParamOption(arg, "A") )
- {
- int style = 0;
- string styleParam = getParam(arg, "A");
- if (styleParam.length() > 0)
- style = atoi(styleParam.c_str());
- if (style == 1)
- formatter.setFormattingStyle(STYLE_ALLMAN);
- else if (style == 2)
- formatter.setFormattingStyle(STYLE_JAVA);
- else if (style == 3)
- formatter.setFormattingStyle(STYLE_KR);
- else if (style == 4)
- formatter.setFormattingStyle(STYLE_STROUSTRUP);
- else if (style == 5)
- formatter.setFormattingStyle(STYLE_WHITESMITH);
- else if (style == 6)
- formatter.setFormattingStyle(STYLE_BANNER);
- else if (style == 7)
- formatter.setFormattingStyle(STYLE_GNU);
- else if (style == 8)
- formatter.setFormattingStyle(STYLE_LINUX);
- else if (style == 9)
- formatter.setFormattingStyle(STYLE_HORSTMANN);
- else if (style == 10)
- formatter.setFormattingStyle(STYLE_1TBS);
- else if (style == 11)
- formatter.setFormattingStyle(STYLE_PICO);
- else if (style == 12)
- formatter.setFormattingStyle(STYLE_LISP);
- else if (style == 14)
- formatter.setFormattingStyle(STYLE_GOOGLE);
- else if (style == 15)
- formatter.setFormattingStyle(STYLE_VTK);
- else if (style == 16)
- formatter.setFormattingStyle(STYLE_MOZILLA);
- else
- isOptionError(arg, errorInfo);
- }
- // must check for mode=cs before mode=c !!!
- else if ( isOption(arg, "mode=cs") )
- {
- formatter.setSharpStyle();
- formatter.setModeManuallySet(true);
- }
- else if ( isOption(arg, "mode=c") )
- {
- formatter.setCStyle();
- formatter.setModeManuallySet(true);
- }
- else if ( isOption(arg, "mode=java") )
- {
- formatter.setJavaStyle();
- formatter.setModeManuallySet(true);
- }
- else if ( isParamOption(arg, "t", "indent=tab=") )
- {
- int spaceNum = 4;
- string spaceNumParam = getParam(arg, "t", "indent=tab=");
- if (spaceNumParam.length() > 0)
- spaceNum = atoi(spaceNumParam.c_str());
- if (spaceNum < 2 || spaceNum > 20)
- isOptionError(arg, errorInfo);
- else
- {
- formatter.setTabIndentation(spaceNum, false);
- }
- }
- else if ( isOption(arg, "indent=tab") )
- {
- formatter.setTabIndentation(4);
- }
- else if ( isParamOption(arg, "T", "indent=force-tab=") )
- {
- int spaceNum = 4;
- string spaceNumParam = getParam(arg, "T", "indent=force-tab=");
- if (spaceNumParam.length() > 0)
- spaceNum = atoi(spaceNumParam.c_str());
- if (spaceNum < 2 || spaceNum > 20)
- isOptionError(arg, errorInfo);
- else
- {
- formatter.setTabIndentation(spaceNum, true);
- }
- }
- else if ( isOption(arg, "indent=force-tab") )
- {
- formatter.setTabIndentation(4, true);
- }
- else if ( isParamOption(arg, "xT", "indent=force-tab-x=") )
- {
- int tabNum = 8;
- string tabNumParam = getParam(arg, "xT", "indent=force-tab-x=");
- if (tabNumParam.length() > 0)
- tabNum = atoi(tabNumParam.c_str());
- if (tabNum < 2 || tabNum > 20)
- isOptionError(arg, errorInfo);
- else
- {
- formatter.setForceTabXIndentation(tabNum);
- }
- }
- else if ( isOption(arg, "indent=force-tab-x") )
- {
- formatter.setForceTabXIndentation(8);
- }
- else if ( isParamOption(arg, "s", "indent=spaces=") )
- {
- int spaceNum = 4;
- string spaceNumParam = getParam(arg, "s", "indent=spaces=");
- if (spaceNumParam.length() > 0)
- spaceNum = atoi(spaceNumParam.c_str());
- if (spaceNum < 2 || spaceNum > 20)
- isOptionError(arg, errorInfo);
- else
- {
- formatter.setSpaceIndentation(spaceNum);
- }
- }
- else if ( isOption(arg, "indent=spaces") )
- {
- formatter.setSpaceIndentation(4);
- }
- else if (isParamOption(arg, "xt", "indent-continuation="))
- {
- int contIndent = 1;
- string contIndentParam = getParam(arg, "xt", "indent-continuation=");
- if (contIndentParam.length() > 0)
- contIndent = atoi(contIndentParam.c_str());
- if (contIndent < 0)
- isOptionError(arg, errorInfo);
- else if (contIndent > 4)
- isOptionError(arg, errorInfo);
- else
- formatter.setContinuationIndentation(contIndent);
- }
- else if ( isParamOption(arg, "m", "min-conditional-indent=") )
- {
- int minIndent = MINCOND_TWO;
- string minIndentParam = getParam(arg, "m", "min-conditional-indent=");
- if (minIndentParam.length() > 0)
- minIndent = atoi(minIndentParam.c_str());
- if (minIndent >= MINCOND_END)
- isOptionError(arg, errorInfo);
- else
- formatter.setMinConditionalIndentOption(minIndent);
- }
- else if ( isParamOption(arg, "M", "max-continuation-indent=") )
- {
- int maxIndent = 40;
- string maxIndentParam = getParam(arg, "M", "max-continuation-indent=");
- if (maxIndentParam.length() > 0)
- maxIndent = atoi(maxIndentParam.c_str());
- if (maxIndent < 40)
- isOptionError(arg, errorInfo);
- else if (maxIndent > 120)
- isOptionError(arg, errorInfo);
- else
- formatter.setMaxContinuationIndentLength(maxIndent);
- }
- else if ( isOption(arg, "N", "indent-namespaces") )
- {
- formatter.setNamespaceIndent(true);
- }
- else if ( isOption(arg, "C", "indent-classes") )
- {
- formatter.setClassIndent(true);
- }
- else if ( isOption(arg, "xG", "indent-modifiers") )
- {
- formatter.setModifierIndent(true);
- }
- else if ( isOption(arg, "S", "indent-switches") )
- {
- formatter.setSwitchIndent(true);
- }
- else if ( isOption(arg, "K", "indent-cases") )
- {
- formatter.setCaseIndent(true);
- }
- else if ( isOption(arg, "xU", "indent-after-parens") )
- {
- formatter.setAfterParenIndent(true);
- }
- else if ( isOption(arg, "L", "indent-labels") )
- {
- formatter.setLabelIndent(true);
- }
- else if (isOption(arg, "xW", "indent-preproc-block"))
- {
- formatter.setPreprocBlockIndent(true);
- }
- else if ( isOption(arg, "w", "indent-preproc-define") )
- {
- formatter.setPreprocDefineIndent(true);
- }
- else if ( isOption(arg, "xw", "indent-preproc-cond") )
- {
- formatter.setPreprocConditionalIndent(true);
- }
- else if ( isOption(arg, "y", "break-closing-braces") )
- {
- formatter.setBreakClosingHeaderBracesMode(true);
- }
- else if ( isOption(arg, "O", "keep-one-line-blocks") )
- {
- formatter.setBreakOneLineBlocksMode(false);
- }
- else if ( isOption(arg, "o", "keep-one-line-statements") )
- {
- formatter.setBreakOneLineStatementsMode(false);
- }
- else if ( isOption(arg, "P", "pad-paren") )
- {
- formatter.setParensOutsidePaddingMode(true);
- formatter.setParensInsidePaddingMode(true);
- }
- else if ( isOption(arg, "d", "pad-paren-out") )
- {
- formatter.setParensOutsidePaddingMode(true);
- }
- else if ( isOption(arg, "xd", "pad-first-paren-out") )
- {
- formatter.setParensFirstPaddingMode(true);
- }
- else if ( isOption(arg, "D", "pad-paren-in") )
- {
- formatter.setParensInsidePaddingMode(true);
- }
- else if ( isOption(arg, "H", "pad-header") )
- {
- formatter.setParensHeaderPaddingMode(true);
- }
- else if ( isOption(arg, "U", "unpad-paren") )
- {
- formatter.setParensUnPaddingMode(true);
- }
- else if ( isOption(arg, "p", "pad-oper") )
- {
- formatter.setOperatorPaddingMode(true);
- }
- else if (isOption(arg, "xg", "pad-comma"))
- {
- formatter.setCommaPaddingMode(true);
- }
- else if ( isOption(arg, "xe", "delete-empty-lines") )
- {
- formatter.setDeleteEmptyLinesMode(true);
- }
- else if ( isOption(arg, "E", "fill-empty-lines") )
- {
- formatter.setEmptyLineFill(true);
- }
- else if ( isOption(arg, "c", "convert-tabs") )
- {
- formatter.setTabSpaceConversionMode(true);
- }
- else if ( isOption(arg, "xy", "close-templates") )
- {
- formatter.setCloseTemplatesMode(true);
- }
- else if ( isOption(arg, "F", "break-blocks=all") )
- {
- formatter.setBreakBlocksMode(true);
- formatter.setBreakClosingHeaderBlocksMode(true);
- }
- else if ( isOption(arg, "f", "break-blocks") )
- {
- formatter.setBreakBlocksMode(true);
- }
- else if ( isOption(arg, "e", "break-elseifs") )
- {
- formatter.setBreakElseIfsMode(true);
- }
- else if ( isOption(arg, "xb", "break-one-line-headers") )
- {
- formatter.setBreakOneLineHeadersMode(true);
- }
- else if ( isOption(arg, "j", "add-braces") )
- {
- formatter.setAddBracesMode(true);
- }
- else if ( isOption(arg, "J", "add-one-line-braces") )
- {
- formatter.setAddOneLineBracesMode(true);
- }
- else if ( isOption(arg, "xj", "remove-braces") )
- {
- formatter.setRemoveBracesMode(true);
- }
- else if ( isOption(arg, "Y", "indent-col1-comments") )
- {
- formatter.setIndentCol1CommentsMode(true);
- }
- else if ( isOption(arg, "align-pointer=type") )
- {
- formatter.setPointerAlignment(PTR_ALIGN_TYPE);
- }
- else if ( isOption(arg, "align-pointer=middle") )
- {
- formatter.setPointerAlignment(PTR_ALIGN_MIDDLE);
- }
- else if ( isOption(arg, "align-pointer=name") )
- {
- formatter.setPointerAlignment(PTR_ALIGN_NAME);
- }
- else if ( isParamOption(arg, "k") )
- {
- int align = 0;
- string styleParam = getParam(arg, "k");
- if (styleParam.length() > 0)
- align = atoi(styleParam.c_str());
- if (align < 1 || align > 3)
- isOptionError(arg, errorInfo);
- else if (align == 1)
- formatter.setPointerAlignment(PTR_ALIGN_TYPE);
- else if (align == 2)
- formatter.setPointerAlignment(PTR_ALIGN_MIDDLE);
- else if (align == 3)
- formatter.setPointerAlignment(PTR_ALIGN_NAME);
- }
- else if ( isOption(arg, "align-reference=none") )
- {
- formatter.setReferenceAlignment(REF_ALIGN_NONE);
- }
- else if ( isOption(arg, "align-reference=type") )
- {
- formatter.setReferenceAlignment(REF_ALIGN_TYPE);
- }
- else if ( isOption(arg, "align-reference=middle") )
- {
- formatter.setReferenceAlignment(REF_ALIGN_MIDDLE);
- }
- else if ( isOption(arg, "align-reference=name") )
- {
- formatter.setReferenceAlignment(REF_ALIGN_NAME);
- }
- else if ( isParamOption(arg, "W") )
- {
- int align = 0;
- string styleParam = getParam(arg, "W");
- if (styleParam.length() > 0)
- align = atoi(styleParam.c_str());
- if (align < 0 || align > 3)
- isOptionError(arg, errorInfo);
- else if (align == 0)
- formatter.setReferenceAlignment(REF_ALIGN_NONE);
- else if (align == 1)
- formatter.setReferenceAlignment(REF_ALIGN_TYPE);
- else if (align == 2)
- formatter.setReferenceAlignment(REF_ALIGN_MIDDLE);
- else if (align == 3)
- formatter.setReferenceAlignment(REF_ALIGN_NAME);
- }
- else if ( isParamOption(arg, "max-code-length=") )
- {
- int maxLength = 50;
- string maxLengthParam = getParam(arg, "max-code-length=");
- if (maxLengthParam.length() > 0)
- maxLength = atoi(maxLengthParam.c_str());
- if (maxLength < 50)
- isOptionError(arg, errorInfo);
- else if (maxLength > 200)
- isOptionError(arg, errorInfo);
- else
- formatter.setMaxCodeLength(maxLength);
- }
- else if ( isParamOption(arg, "xC") )
- {
- int maxLength = 50;
- string maxLengthParam = getParam(arg, "xC");
- if (maxLengthParam.length() > 0)
- maxLength = atoi(maxLengthParam.c_str());
- if (maxLength > 200)
- isOptionError(arg, errorInfo);
- else
- formatter.setMaxCodeLength(maxLength);
- }
- else if ( isOption(arg, "xL", "break-after-logical") )
- {
- formatter.setBreakAfterMode(true);
- }
- else if ( isOption(arg, "xc", "attach-classes") )
- {
- formatter.setAttachClass(true);
- }
- else if ( isOption(arg, "xV", "attach-closing-while") )
- {
- formatter.setAttachClosingWhile(true);
- }
- else if ( isOption(arg, "xk", "attach-extern-c") )
- {
- formatter.setAttachExternC(true);
- }
- else if ( isOption(arg, "xn", "attach-namespaces") )
- {
- formatter.setAttachNamespace(true);
- }
- else if ( isOption(arg, "xl", "attach-inlines") )
- {
- formatter.setAttachInline(true);
- }
- else if ( isOption(arg, "xp", "remove-comment-prefix") )
- {
- formatter.setStripCommentPrefix(true);
- }
- // Objective-C options
- else if ( isOption(arg, "xQ", "pad-method-prefix") )
- {
- formatter.setMethodPrefixPaddingMode(true);
- }
- else if ( isOption(arg, "xR", "unpad-method-prefix") )
- {
- formatter.setMethodPrefixUnPaddingMode(true);
- }
- else if (isOption(arg, "xq", "pad-return-type"))
- {
- formatter.setReturnTypePaddingMode(true);
- }
- else if (isOption(arg, "xr", "unpad-return-type"))
- {
- formatter.setReturnTypeUnPaddingMode(true);
- }
- else if (isOption(arg, "xS", "pad-param-type"))
- {
- formatter.setParamTypePaddingMode(true);
- }
- else if (isOption(arg, "xs", "unpad-param-type"))
- {
- formatter.setParamTypeUnPaddingMode(true);
- }
- else if (isOption(arg, "xM", "align-method-colon"))
- {
- formatter.setAlignMethodColon(true);
- }
- else if ( isOption(arg, "xP0", "pad-method-colon=none") )
- {
- formatter.setObjCColonPaddingMode(COLON_PAD_NONE);
- }
- else if ( isOption(arg, "xP1", "pad-method-colon=all") )
- {
- formatter.setObjCColonPaddingMode(COLON_PAD_ALL);
- }
- else if ( isOption(arg, "xP2", "pad-method-colon=after") )
- {
- formatter.setObjCColonPaddingMode(COLON_PAD_AFTER);
- }
- else if ( isOption(arg, "xP3", "pad-method-colon=before") )
- {
- formatter.setObjCColonPaddingMode(COLON_PAD_BEFORE);
- }
- // depreciated options ////////////////////////////////////////////////////////////////////////
- else if ( isOption(arg, "indent-preprocessor") ) // depreciated release 2.04
- {
- formatter.setPreprocDefineIndent(true);
- }
- else if ( isOption(arg, "style=ansi") ) // depreciated release 2.05
- {
- formatter.setFormattingStyle(STYLE_ALLMAN);
- }
- // depreciated in release 3.0 /////////////////////////////////////////////////////////////////
- else if ( isOption(arg, "break-closing-brackets") ) // depreciated release 3.0
- {
- formatter.setBreakClosingHeaderBracketsMode(true);
- }
- else if ( isOption(arg, "add-brackets") ) // depreciated release 3.0
- {
- formatter.setAddBracketsMode(true);
- }
- else if ( isOption(arg, "add-one-line-brackets") ) // depreciated release 3.0
- {
- formatter.setAddOneLineBracketsMode(true);
- }
- else if ( isOption(arg, "remove-brackets") ) // depreciated release 3.0
- {
- formatter.setRemoveBracketsMode(true);
- }
- else if ( isParamOption(arg, "max-instatement-indent=") ) // depreciated release 3.0
- {
- int maxIndent = 40;
- string maxIndentParam = getParam(arg, "max-instatement-indent=");
- if (maxIndentParam.length() > 0)
- maxIndent = atoi(maxIndentParam.c_str());
- if (maxIndent < 40)
- isOptionError(arg, errorInfo);
- else if (maxIndent > 120)
- isOptionError(arg, errorInfo);
- else
- formatter.setMaxInStatementIndentLength(maxIndent);
- }
- // NOTE: Removed in release 2.04.
- // else if ( isOption(arg, "b", "brackets=break") )
- // {
- // formatter.setBracketFormatMode(BREAK_MODE);
- // }
- // else if ( isOption(arg, "a", "brackets=attach") )
- // {
- // formatter.setBracketFormatMode(ATTACH_MODE);
- // }
- // else if ( isOption(arg, "l", "brackets=linux") )
- // {
- // formatter.setBracketFormatMode(LINUX_MODE);
- // }
- // else if ( isOption(arg, "u", "brackets=stroustrup") )
- // {
- // formatter.setBracketFormatMode(STROUSTRUP_MODE);
- // }
- // else if ( isOption(arg, "g", "brackets=run-in") )
- // {
- // formatter.setBracketFormatMode(RUN_IN_MODE);
- // }
- // end depreciated options ////////////////////////////////////////////////////////////////////
- #ifdef ASTYLE_LIB
- // End of options used by GUI /////////////////////////////////////////////////////////////////
- else
- isOptionError(arg, errorInfo);
- #else
- // Options used by only console ///////////////////////////////////////////////////////////////
- else if ( isOption(arg, "n", "suffix=none") )
- {
- console.setNoBackup(true);
- }
- else if ( isParamOption(arg, "suffix=") )
- {
- string suffixParam = getParam(arg, "suffix=");
- if (suffixParam.length() > 0)
- {
- console.setOrigSuffix(suffixParam);
- }
- }
- else if ( isParamOption(arg, "exclude=") )
- {
- string suffixParam = getParam(arg, "exclude=");
- if (suffixParam.length() > 0)
- console.updateExcludeVector(suffixParam);
- }
- else if ( isOption(arg, "r", "R") || isOption(arg, "recursive") )
- {
- console.setIsRecursive(true);
- }
- else if (isOption(arg, "dry-run"))
- {
- console.setIsDryRun(true);
- }
- else if ( isOption(arg, "Z", "preserve-date") )
- {
- console.setPreserveDate(true);
- }
- else if ( isOption(arg, "v", "verbose") )
- {
- console.setIsVerbose(true);
- }
- else if ( isOption(arg, "Q", "formatted") )
- {
- console.setIsFormattedOnly(true);
- }
- else if ( isOption(arg, "q", "quiet") )
- {
- console.setIsQuiet(true);
- }
- else if ( isOption(arg, "i", "ignore-exclude-errors") )
- {
- console.setIgnoreExcludeErrors(true);
- }
- else if ( isOption(arg, "xi", "ignore-exclude-errors-x") )
- {
- console.setIgnoreExcludeErrorsAndDisplay(true);
- }
- else if ( isOption(arg, "X", "errors-to-stdout") )
- {
- console.setErrorStream(&cout);
- }
- else if ( isOption(arg, "lineend=windows") )
- {
- formatter.setLineEndFormat(LINEEND_WINDOWS);
- }
- else if ( isOption(arg, "lineend=linux") )
- {
- formatter.setLineEndFormat(LINEEND_LINUX);
- }
- else if ( isOption(arg, "lineend=macold") )
- {
- formatter.setLineEndFormat(LINEEND_MACOLD);
- }
- else if ( isParamOption(arg, "z") )
- {
- int lineendType = 0;
- string lineendParam = getParam(arg, "z");
- if (lineendParam.length() > 0)
- lineendType = atoi(lineendParam.c_str());
- if (lineendType < 1 || lineendType > 3)
- isOptionError(arg, errorInfo);
- else if (lineendType == 1)
- formatter.setLineEndFormat(LINEEND_WINDOWS);
- else if (lineendType == 2)
- formatter.setLineEndFormat(LINEEND_LINUX);
- else if (lineendType == 3)
- formatter.setLineEndFormat(LINEEND_MACOLD);
- }
- else if ( isParamOption(arg, "stdin=") )
- {
- string path = getParam(arg, "stdin=");
- console.standardizePath(path);
- console.setStdPathIn(path);
- }
- else if ( isParamOption(arg, "stdout=") )
- {
- string path = getParam(arg, "stdout=");
- console.standardizePath(path);
- console.setStdPathOut(path);
- }
- else
- isOptionError(arg, errorInfo);
- #endif
- } // End of parseOption function
- // Parse options from the options file.
- void ASOptions::importOptions(istream& in, vector<string>& optionsVector)
- {
- char ch;
- bool isInQuote = false;
- char quoteChar = ' ';
- string currentToken;
- while (in)
- {
- currentToken = "";
- do
- {
- in.get(ch);
- if (in.eof())
- break;
- // treat '#' as line comments
- if (ch == '#')
- while (in)
- {
- in.get(ch);
- if (ch == '\n' || ch == '\r')
- break;
- }
- // break options on new-lines, tabs, commas, or spaces
- // remove quotes from output
- if (in.eof() || ch == '\n' || ch == '\r' || ch == '\t' || ch == ',')
- break;
- if (ch == ' ' && !isInQuote)
- break;
- if (ch == quoteChar && isInQuote)
- break;
- if (ch == '"' || ch == '\'')
- {
- isInQuote = true;
- quoteChar = ch;
- continue;
- }
- currentToken.append(1, ch);
- }
- while (in);
- if (currentToken.length() != 0)
- optionsVector.emplace_back(currentToken);
- isInQuote = false;
- }
- }
- string ASOptions::getOptionErrors() const
- {
- return optionErrors.str();
- }
- string ASOptions::getParam(const string& arg, const char* op)
- {
- return arg.substr(strlen(op));
- }
- string ASOptions::getParam(const string& arg, const char* op1, const char* op2)
- {
- return isParamOption(arg, op1) ? getParam(arg, op1) : getParam(arg, op2);
- }
- bool ASOptions::isOption(const string& arg, const char* op)
- {
- return arg.compare(op) == 0;
- }
- bool ASOptions::isOption(const string& arg, const char* op1, const char* op2)
- {
- return (isOption(arg, op1) || isOption(arg, op2));
- }
- void ASOptions::isOptionError(const string& arg, const string& errorInfo)
- {
- if (optionErrors.str().length() == 0)
- optionErrors << errorInfo << endl; // need main error message
- optionErrors << arg << endl;
- }
- bool ASOptions::isParamOption(const string& arg, const char* option)
- {
- bool retVal = arg.compare(0, strlen(option), option) == 0;
- // if comparing for short option, 2nd char of arg must be numeric
- if (retVal && strlen(option) == 1 && arg.length() > 1)
- if (!isdigit((unsigned char)arg[1]))
- retVal = false;
- return retVal;
- }
- bool ASOptions::isParamOption(const string& arg, const char* option1, const char* option2)
- {
- return isParamOption(arg, option1) || isParamOption(arg, option2);
- }
- //----------------------------------------------------------------------------
- // ASEncoding class
- //----------------------------------------------------------------------------
- // Return true if an int is big endian.
- bool ASEncoding::getBigEndian() const
- {
- short int word = 0x0001;
- char* byte = (char*) &word;
- return (byte[0] ? false : true);
- }
- // Swap the two low order bytes of a 16 bit integer value.
- int ASEncoding::swap16bit(int value) const
- {
- return ( ((value & 0xff) << 8) | ((value & 0xff00) >> 8) );
- }
- // Return the length of a utf-16 C string.
- // The length is in number of utf16_t.
- size_t ASEncoding::utf16len(const utf16* utf16In) const
- {
- size_t length = 0;
- while (*utf16In++ != '\0')
- length++;
- return length;
- }
- // Adapted from SciTE UniConversion.cxx.
- // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
- // Modified for Artistic Style by Jim Pattee.
- // Compute the length of an output utf-8 file given a utf-16 file.
- // Input inLen is the size in BYTES (not wchar_t).
- size_t ASEncoding::utf8LengthFromUtf16(const char* utf16In, size_t inLen, bool isBigEndian) const
- {
- size_t len = 0;
- size_t wcharLen = inLen / 2;
- const short* uptr = reinterpret_cast<const short*>(utf16In);
- for (size_t i = 0; i < wcharLen && uptr[i];)
- {
- size_t uch = isBigEndian ? swap16bit(uptr[i]) : uptr[i];
- if (uch < 0x80)
- len++;
- else if (uch < 0x800)
- len += 2;
- else if ((uch >= SURROGATE_LEAD_FIRST) && (uch <= SURROGATE_TRAIL_LAST))
- {
- len += 4;
- i++;
- }
- else
- len += 3;
- i++;
- }
- return len;
- }
- // Adapted from SciTE Utf8_16.cxx.
- // Copyright (C) 2002 Scott Kirkwood.
- // Modified for Artistic Style by Jim Pattee.
- // Convert a utf-8 file to utf-16.
- size_t ASEncoding::utf8ToUtf16(char* utf8In, size_t inLen, bool isBigEndian, char* utf16Out) const
- {
- int nCur = 0;
- ubyte* pRead = reinterpret_cast<ubyte*>(utf8In);
- utf16* pCur = reinterpret_cast<utf16*>(utf16Out);
- const ubyte* pEnd = pRead + inLen;
- const utf16* pCurStart = pCur;
- eState state = eStart;
- // the BOM will automatically be converted to utf-16
- while (pRead < pEnd)
- {
- switch (state)
- {
- case eStart:
- if ((0xF0 & *pRead) == 0xF0)
- {
- nCur = (0x7 & *pRead) << 18;
- state = eSecondOf4Bytes;
- }
- else if ((0xE0 & *pRead) == 0xE0)
- {
- nCur = (~0xE0 & *pRead) << 12;
- state = ePenultimate;
- }
- else if ((0xC0 & *pRead) == 0xC0)
- {
- nCur = (~0xC0 & *pRead) << 6;
- state = eFinal;
- }
- else
- {
- nCur = *pRead;
- state = eStart;
- }
- break;
- case eSecondOf4Bytes:
- nCur |= (0x3F & *pRead) << 12;
- state = ePenultimate;
- break;
- case ePenultimate:
- nCur |= (0x3F & *pRead) << 6;
- state = eFinal;
- break;
- case eFinal:
- nCur |= (0x3F & *pRead);
- state = eStart;
- break;
- // no default case is needed
- }
- ++pRead;
- if (state == eStart)
- {
- int codePoint = nCur;
- if (codePoint >= SURROGATE_FIRST_VALUE)
- {
- codePoint -= SURROGATE_FIRST_VALUE;
- int lead = (codePoint >> 10) + SURROGATE_LEAD_FIRST;
- *pCur++ = static_cast<utf16>(isBigEndian ? swap16bit(lead) : lead);
- int trail = (codePoint & 0x3ff) + SURROGATE_TRAIL_FIRST;
- *pCur++ = static_cast<utf16>(isBigEndian ? swap16bit(trail) : trail);
- }
- else
- *pCur++ = static_cast<utf16>(isBigEndian ? swap16bit(codePoint) : codePoint);
- }
- }
- // return value is the output length in BYTES (not wchar_t)
- return (pCur - pCurStart) * 2;
- }
- // Adapted from SciTE UniConversion.cxx.
- // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
- // Modified for Artistic Style by Jim Pattee.
- // Compute the length of an output utf-16 file given a utf-8 file.
- // Return value is the size in BYTES (not wchar_t).
- size_t ASEncoding::utf16LengthFromUtf8(const char* utf8In, size_t len) const
- {
- size_t ulen = 0;
- size_t charLen;
- for (size_t i = 0; i < len;)
- {
- unsigned char ch = static_cast<unsigned char>(utf8In[i]);
- if (ch < 0x80)
- charLen = 1;
- else if (ch < 0x80 + 0x40 + 0x20)
- charLen = 2;
- else if (ch < 0x80 + 0x40 + 0x20 + 0x10)
- charLen = 3;
- else
- {
- charLen = 4;
- ulen++;
- }
- i += charLen;
- ulen++;
- }
- // return value is the length in bytes (not wchar_t)
- return ulen * 2;
- }
- // Adapted from SciTE Utf8_16.cxx.
- // Copyright (C) 2002 Scott Kirkwood.
- // Modified for Artistic Style by Jim Pattee.
- // Convert a utf-16 file to utf-8.
- size_t ASEncoding::utf16ToUtf8(char* utf16In, size_t inLen, bool isBigEndian,
- bool firstBlock, char* utf8Out) const
- {
- int nCur16 = 0;
- int nCur = 0;
- ubyte* pRead = reinterpret_cast<ubyte*>(utf16In);
- ubyte* pCur = reinterpret_cast<ubyte*>(utf8Out);
- const ubyte* pEnd = pRead + inLen;
- const ubyte* pCurStart = pCur;
- static eState state = eStart; // state is retained for subsequent blocks
- if (firstBlock)
- state = eStart;
- // the BOM will automatically be converted to utf-8
- while (pRead < pEnd)
- {
- switch (state)
- {
- case eStart:
- if (pRead >= pEnd)
- {
- ++pRead;
- break;
- }
- if (isBigEndian)
- {
- nCur16 = static_cast<utf16>(*pRead++ << 8);
- nCur16 |= static_cast<utf16>(*pRead);
- }
- else
- {
- nCur16 = *pRead++;
- nCur16 |= static_cast<utf16>(*pRead << 8);
- }
- if (nCur16 >= SURROGATE_LEAD_FIRST && nCur16 <= SURROGATE_LEAD_LAST)
- {
- ++pRead;
- int trail;
- if (isBigEndian)
- {
- trail = static_cast<utf16>(*pRead++ << 8);
- trail |= static_cast<utf16>(*pRead);
- }
- else
- {
- trail = *pRead++;
- trail |= static_cast<utf16>(*pRead << 8);
- }
- nCur16 = (((nCur16 & 0x3ff) << 10) | (trail & 0x3ff)) + SURROGATE_FIRST_VALUE;
- }
- ++pRead;
- if (nCur16 < 0x80)
- {
- nCur = static_cast<ubyte>(nCur16 & 0xFF);
- state = eStart;
- }
- else if (nCur16 < 0x800)
- {
- nCur = static_cast<ubyte>(0xC0 | (nCur16 >> 6));
- state = eFinal;
- }
- else if (nCur16 < SURROGATE_FIRST_VALUE)
- {
- nCur = static_cast<ubyte>(0xE0 | (nCur16 >> 12));
- state = ePenultimate;
- }
- else
- {
- nCur = static_cast<ubyte>(0xF0 | (nCur16 >> 18));
- state = eSecondOf4Bytes;
- }
- break;
- case eSecondOf4Bytes:
- nCur = static_cast<ubyte>(0x80 | ((nCur16 >> 12) & 0x3F));
- state = ePenultimate;
- break;
- case ePenultimate:
- nCur = static_cast<ubyte>(0x80 | ((nCur16 >> 6) & 0x3F));
- state = eFinal;
- break;
- case eFinal:
- nCur = static_cast<ubyte>(0x80 | (nCur16 & 0x3F));
- state = eStart;
- break;
- // no default case is needed
- }
- *pCur++ = static_cast<ubyte>(nCur);
- }
- return pCur - pCurStart;
- }
- //----------------------------------------------------------------------------
- } // namespace astyle
- //----------------------------------------------------------------------------
- using namespace astyle;
- //----------------------------------------------------------------------------
- // ASTYLE_JNI functions for Java library builds
- //----------------------------------------------------------------------------
- #ifdef ASTYLE_JNI
- // called by a java program to get the version number
- // the function name is constructed from method names in the calling java program
- extern "C" EXPORT
- jstring STDCALL Java_AStyleInterface_AStyleGetVersion(JNIEnv* env, jclass)
- {
- return env->NewStringUTF(g_version);
- }
- // called by a java program to format the source code
- // the function name is constructed from method names in the calling java program
- extern "C" EXPORT
- jstring STDCALL Java_AStyleInterface_AStyleMain(JNIEnv* env,
- jobject obj,
- jstring textInJava,
- jstring optionsJava)
- {
- g_env = env; // make object available globally
- g_obj = obj; // make object available globally
- jstring textErr = env->NewStringUTF(""); // zero length text returned if an error occurs
- // get the method ID
- jclass cls = env->GetObjectClass(obj);
- g_mid = env->GetMethodID(cls, "ErrorHandler", "(ILjava/lang/String;)V");
- if (g_mid == nullptr)
- {
- cout << "Cannot find java method ErrorHandler" << endl;
- return textErr;
- }
- // convert jstring to char*
- const char* textIn = env->GetStringUTFChars(textInJava, nullptr);
- const char* options = env->GetStringUTFChars(optionsJava, nullptr);
- // call the C++ formatting function
- char* textOut = AStyleMain(textIn, options, javaErrorHandler, javaMemoryAlloc);
- // if an error message occurred it was displayed by errorHandler
- if (textOut == nullptr)
- return textErr;
- // release memory
- jstring textOutJava = env->NewStringUTF(textOut);
- delete[] textOut;
- env->ReleaseStringUTFChars(textInJava, textIn);
- env->ReleaseStringUTFChars(optionsJava, options);
- return textOutJava;
- }
- // Call the Java error handler
- void STDCALL javaErrorHandler(int errorNumber, const char* errorMessage)
- {
- jstring errorMessageJava = g_env->NewStringUTF(errorMessage);
- g_env->CallVoidMethod(g_obj, g_mid, errorNumber, errorMessageJava);
- }
- // Allocate memory for the formatted text
- char* STDCALL javaMemoryAlloc(unsigned long memoryNeeded)
- {
- // error condition is checked after return from AStyleMain
- char* buffer = new (nothrow) char[memoryNeeded];
- return buffer;
- }
- #endif // ASTYLE_JNI
- //----------------------------------------------------------------------------
- // ASTYLE_LIB functions for library builds
- //----------------------------------------------------------------------------
- #ifdef ASTYLE_LIB
- //----------------------------------------------------------------------------
- // ASTYLE_LIB entry point for AStyleMainUtf16 library builds
- //----------------------------------------------------------------------------
- /*
- * IMPORTANT Visual C DLL linker for WIN32 must have the additional options:
- * /EXPORT:AStyleMain=_AStyleMain@16
- * /EXPORT:AStyleMainUtf16=_AStyleMainUtf16@16
- * /EXPORT:AStyleGetVersion=_AStyleGetVersion@0
- * No /EXPORT is required for x64
- */
- extern "C" EXPORT utf16_t* STDCALL AStyleMainUtf16(const utf16_t* pSourceIn, // the source to be formatted
- const utf16_t* pOptions, // AStyle options
- fpError fpErrorHandler, // error handler function
- fpAlloc fpMemoryAlloc) // memory allocation function
- {
- if (fpErrorHandler == nullptr) // cannot display a message if no error handler
- return nullptr;
- if (pSourceIn == nullptr)
- {
- fpErrorHandler(101, "No pointer to source input.");
- return nullptr;
- }
- if (pOptions == nullptr)
- {
- fpErrorHandler(102, "No pointer to AStyle options.");
- return nullptr;
- }
- if (fpMemoryAlloc == nullptr)
- {
- fpErrorHandler(103, "No pointer to memory allocation function.");
- return nullptr;
- }
- #ifndef _WIN32
- // check size of utf16_t on Linux
- int sizeCheck = 2;
- if (sizeof(utf16_t) != sizeCheck)
- {
- fpErrorHandler(104, "Unsigned short is not the correct size.");
- return nullptr;
- }
- #endif
- ASLibrary library;
- utf16_t* utf16Out = library.formatUtf16(pSourceIn, pOptions, fpErrorHandler, fpMemoryAlloc);
- return utf16Out;
- }
- //----------------------------------------------------------------------------
- // ASTYLE_LIB entry point for library builds
- //----------------------------------------------------------------------------
- /*
- * IMPORTANT Visual C DLL linker for WIN32 must have the additional options:
- * /EXPORT:AStyleMain=_AStyleMain@16
- * /EXPORT:AStyleMainUtf16=_AStyleMainUtf16@16
- * /EXPORT:AStyleGetVersion=_AStyleGetVersion@0
- * No /EXPORT is required for x64
- */
- extern "C" EXPORT char* STDCALL AStyleMain(const char* pSourceIn, // the source to be formatted
- const char* pOptions, // AStyle options
- fpError fpErrorHandler, // error handler function
- fpAlloc fpMemoryAlloc) // memory allocation function
- {
- if (fpErrorHandler == nullptr) // cannot display a message if no error handler
- return nullptr;
- if (pSourceIn == nullptr)
- {
- fpErrorHandler(101, "No pointer to source input.");
- return nullptr;
- }
- if (pOptions == nullptr)
- {
- fpErrorHandler(102, "No pointer to AStyle options.");
- return nullptr;
- }
- if (fpMemoryAlloc == nullptr)
- {
- fpErrorHandler(103, "No pointer to memory allocation function.");
- return nullptr;
- }
- ASFormatter formatter;
- ASOptions options(formatter);
- vector<string> optionsVector;
- istringstream opt(pOptions);
- options.importOptions(opt, optionsVector);
- bool ok = options.parseOptions(optionsVector, "Invalid Artistic Style options:");
- if (!ok)
- fpErrorHandler(130, options.getOptionErrors().c_str());
- istringstream in(pSourceIn);
- ASStreamIterator<istringstream> streamIterator(&in);
- ostringstream out;
- formatter.init(&streamIterator);
- while (formatter.hasMoreLines())
- {
- out << formatter.nextLine();
- if (formatter.hasMoreLines())
- out << streamIterator.getOutputEOL();
- else
- {
- // this can happen if the file if missing a closing brace and break-blocks is requested
- if (formatter.getIsLineReady())
- {
- out << streamIterator.getOutputEOL();
- out << formatter.nextLine();
- }
- }
- }
- size_t textSizeOut = out.str().length();
- char* pTextOut = fpMemoryAlloc((long)textSizeOut + 1); // call memory allocation function
- if (pTextOut == nullptr)
- {
- fpErrorHandler(120, "Allocation failure on output.");
- return nullptr;
- }
- strcpy(pTextOut, out.str().c_str());
- #ifndef NDEBUG
- // The checksum is an assert in the console build and ASFormatter.
- // This error returns the incorrectly formatted file to the editor.
- // This is done to allow the file to be saved for debugging purposes.
- if (formatter.getChecksumDiff() != 0)
- fpErrorHandler(220,
- "Checksum error.\n"
- "The incorrectly formatted file will be returned for debugging.");
- #endif
- return pTextOut;
- }
- extern "C" EXPORT const char* STDCALL AStyleGetVersion(void)
- {
- return g_version;
- }
- // ASTYLECON_LIB is defined to exclude "main" from the test programs
- #elif !defined(ASTYLECON_LIB)
- //----------------------------------------------------------------------------
- // main function for ASConsole build
- //----------------------------------------------------------------------------
- int main(int argc, char** argv)
- {
- // create objects
- ASFormatter formatter;
- auto console = make_shared<ASConsole>(formatter);
- // process command line and options file
- // build the vectors fileNameVector, optionsVector, and fileOptionsVector
- vector<string> argvOptions;
- argvOptions = console->getArgvOptions(argc, argv);
- console->processOptions(argvOptions);
- // if no files have been given, use cin for input and cout for output
- if (!console->fileNameVectorIsEmpty())
- console->processFiles();
- else
- console->formatCinToCout();
- return EXIT_SUCCESS;
- }
- #endif // ASTYLE_LIB
|