123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877 |
- /********************************************************************************
- * tools/nxstyle.c
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership. The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance with the
- * License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
- * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
- * License for the specific language governing permissions and limitations
- * under the License.
- *
- ********************************************************************************/
- /********************************************************************************
- * Included Files
- ********************************************************************************/
- #include <stdlib.h>
- #include <stdbool.h>
- #include <stdio.h>
- #include <stdint.h>
- #include <string.h>
- #include <strings.h>
- #include <ctype.h>
- #include <limits.h>
- #include <unistd.h>
- #include <libgen.h>
- /********************************************************************************
- * Pre-processor Definitions
- ********************************************************************************/
- #define NXSTYLE_VERSION "0.01"
- #define LINE_SIZE 512
- #define RANGE_NUMBER 4096
- #define DEFAULT_WIDTH 78
- #define FIRST_SECTION INCLUDED_FILES
- #define LAST_SECTION PUBLIC_FUNCTION_PROTOTYPES
- #define FATAL(m, l, o) message(FATAL, (m), (l), (o))
- #define FATALFL(m, s) message(FATAL, (m), -1, -1)
- #define WARN(m, l, o) message(WARN, (m), (l), (o))
- #define ERROR(m, l, o) message(ERROR, (m), (l), (o))
- #define ERRORFL(m, s) message(ERROR, (m), -1, -1)
- #define INFO(m, l, o) message(INFO, (m), (l), (o))
- #define INFOFL(m, s) message(INFO, (m), -1, -1)
- /********************************************************************************
- * Private types
- ********************************************************************************/
- enum class_e
- {
- INFO,
- WARN,
- ERROR,
- FATAL
- };
- const char *class_text[] =
- {
- "info",
- "warning",
- "error",
- "fatal"
- };
- enum file_e
- {
- UNKNOWN = 0x00,
- C_HEADER = 0x01,
- C_SOURCE = 0x02
- };
- enum section_s
- {
- NO_SECTION = 0,
- INCLUDED_FILES,
- PRE_PROCESSOR_DEFINITIONS,
- PUBLIC_TYPES,
- PRIVATE_TYPES,
- PRIVATE_DATA,
- PUBLIC_DATA,
- PRIVATE_FUNCTIONS,
- PRIVATE_FUNCTION_PROTOTYPES,
- INLINE_FUNCTIONS,
- PUBLIC_FUNCTIONS,
- PUBLIC_FUNCTION_PROTOTYPES
- };
- enum pptype_e
- {
- PPLINE_NONE = 0,
- PPLINE_DEFINE,
- PPLINE_IF,
- PPLINE_ELIF,
- PPLINE_ELSE,
- PPLINE_ENDIF,
- PPLINE_OTHER
- };
- struct file_section_s
- {
- const char *name; /* File section name */
- uint8_t ftype; /* File type where section found */
- };
- /********************************************************************************
- * Private data
- ********************************************************************************/
- static enum file_e g_file_type = UNKNOWN;
- static enum section_s g_section = NO_SECTION;
- static int g_maxline = DEFAULT_WIDTH;
- static int g_status = 0;
- static int g_verbose = 2;
- static int g_rangenumber = 0;
- static int g_rangestart[RANGE_NUMBER];
- static int g_rangecount[RANGE_NUMBER];
- static char g_file_name[PATH_MAX];
- static const struct file_section_s g_section_info[] =
- {
- {
- " *\n", /* Index: NO_SECTION */
- C_SOURCE | C_HEADER
- },
- {
- " * Included Files\n", /* Index: INCLUDED_FILES */
- C_SOURCE | C_HEADER
- },
- {
- " * Pre-processor Definitions\n", /* Index: PRE_PROCESSOR_DEFINITIONS */
- C_SOURCE | C_HEADER
- },
- {
- " * Public Types\n", /* Index: PUBLIC_TYPES */
- C_HEADER
- },
- {
- " * Private Types\n", /* Index: PRIVATE_TYPES */
- C_SOURCE
- },
- {
- " * Private Data\n", /* Index: PRIVATE_DATA */
- C_SOURCE
- },
- {
- " * Public Data\n", /* Index: PUBLIC_DATA */
- C_SOURCE | C_HEADER
- },
- {
- " * Private Functions\n", /* Index: PRIVATE_FUNCTIONS */
- C_SOURCE
- },
- {
- " * Private Function Prototypes\n", /* Index: PRIVATE_FUNCTION_PROTOTYPES */
- C_SOURCE
- },
- {
- " * Inline Functions\n", /* Index: INLINE_FUNCTIONS */
- C_SOURCE | C_HEADER
- },
- {
- " * Public Functions\n", /* Index: PUBLIC_FUNCTIONS */
- C_SOURCE
- },
- {
- " * Public Function Prototypes\n", /* Index: PUBLIC_FUNCTION_PROTOTYPES */
- C_SOURCE | C_HEADER
- }
- };
- static const char *g_white_prefix[] =
- {
- "Elf", /* Ref: include/elf.h, include/elf32.h, include/elf64.h */
- "PRId", /* Ref: inttypes.h */
- "PRIi", /* Ref: inttypes.h */
- "PRIo", /* Ref: inttypes.h */
- "PRIu", /* Ref: inttypes.h */
- "PRIx", /* Ref: inttypes.h */
- "SCNd", /* Ref: inttypes.h */
- "SCNi", /* Ref: inttypes.h */
- "SCNo", /* Ref: inttypes.h */
- "SCNu", /* Ref: inttypes.h */
- "SCNx", /* Ref: inttypes.h */
- "SYS_", /* Ref: include/sys/syscall.h */
- "STUB_", /* Ref: syscall/syscall_lookup.h, syscall/sycall_stublookup.c */
- "b8", /* Ref: include/fixedmath.h */
- "b16", /* Ref: include/fixedmath.h */
- "b32", /* Ref: include/fixedmath.h */
- "ub8", /* Ref: include/fixedmath.h */
- "ub16", /* Ref: include/fixedmath.h */
- "ub32", /* Ref: include/fixedmath.h */
- "ASCII_", /* Ref: include/nuttx/ascii.h */
- "XK_", /* Ref: include/input/X11_keysymdef.h */
- NULL
- };
- static const char *g_white_list[] =
- {
- /* Ref: gnu_unwind_find_exidx.c */
- "__EIT_entry",
- /* Ref: gnu_unwind_find_exidx.c */
- "__gnu_Unwind_Find_exidx",
- /* Ref: stdlib.h */
- "_Exit",
- /* Ref: stdatomic.h */
- "_Atomic",
- /* Ref: unwind-arm-common.h */
- "_Unwind",
- /* Ref:
- * https://pubs.opengroup.org/onlinepubs/9699919799/functions/tempnam.html
- */
- "P_tmpdir",
- /* Ref:
- * https://pubs.opengroup.org/onlinepubs/9699919799/functions/tempnam.html
- */
- "L_tmpnam",
- /* Ref:
- * nuttx/compiler.h
- */
- "_Far",
- "_Erom",
- /* Ref:
- * fs/nfs/rpc.h
- * fs/nfs/nfs_proto.h
- */
- "CREATE3args",
- "CREATE3resok",
- "LOOKUP3args",
- "LOOKUP3filename",
- "LOOKUP3resok",
- "WRITE3args",
- "WRITE3resok",
- "READ3args",
- "READ3resok",
- "REMOVE3args",
- "REMOVE3resok",
- "RENAME3args",
- "RENAME3resok",
- "MKDIR3args",
- "MKDIR3resok",
- "RMDIR3args",
- "RMDIR3resok",
- "READDIR3args",
- "READDIR3resok",
- "SETATTR3args",
- "SETATTR3resok",
- "FS3args",
- NULL
- };
- /********************************************************************************
- * Private Functions
- ********************************************************************************/
- /********************************************************************************
- * Name: show_usage
- *
- * Description:
- *
- ********************************************************************************/
- static void show_usage(char *progname, int exitcode, char *what)
- {
- fprintf(stderr, "%s version %s\n\n", basename(progname), NXSTYLE_VERSION);
- if (what)
- {
- fprintf(stderr, "%s\n", what);
- }
- fprintf(stderr, "Usage: %s [-m <excess>] [-v <level>] "
- "[-r <start,count>] <filename>\n",
- basename(progname));
- fprintf(stderr, " %s -h this help\n", basename(progname));
- fprintf(stderr, " %s -v <level> where level is\n",
- basename(progname));
- fprintf(stderr, " 0 - no output\n");
- fprintf(stderr, " 1 - PASS/FAIL\n");
- fprintf(stderr, " 2 - output each line (default)\n");
- exit(exitcode);
- }
- /********************************************************************************
- * Name: skip
- *
- * Description:
- *
- ********************************************************************************/
- static int skip(int lineno)
- {
- int i;
- for (i = 0; i < g_rangenumber; i++)
- {
- if (lineno >= g_rangestart[i] && lineno < g_rangestart[i] +
- g_rangecount[i])
- {
- return 0;
- }
- }
- return g_rangenumber != 0;
- }
- /********************************************************************************
- * Name: message
- *
- * Description:
- *
- ********************************************************************************/
- static int message(enum class_e class, const char *text, int lineno, int ndx)
- {
- FILE *out = stdout;
- if (skip(lineno))
- {
- return g_status;
- }
- if (class > INFO)
- {
- out = stderr;
- g_status |= 1;
- }
- if (g_verbose == 2)
- {
- if (lineno == -1 && ndx == -1)
- {
- fprintf(out, "%s: %s: %s\n", g_file_name, class_text[class], text);
- }
- else
- {
- fprintf(out, "%s:%d:%d: %s: %s\n", g_file_name, lineno, ndx,
- class_text[class], text);
- }
- }
- return g_status;
- }
- /********************************************************************************
- * Name: check_spaces_left
- *
- * Description:
- *
- ********************************************************************************/
- static void check_spaces_left(char *line, int lineno, int ndx)
- {
- /* Unary operator should generally be preceded by a space but make also
- * follow a left parenthesis at the beginning of a parenthetical list or
- * expression or follow a right parentheses in the case of a cast.
- */
- if (ndx-- > 0 && line[ndx] != ' ' && line[ndx] != '(' && line[ndx] != ')')
- {
- ERROR("Operator/assignment must be preceded with whitespace",
- lineno, ndx);
- }
- }
- /********************************************************************************
- * Name: check_spaces_leftright
- *
- * Description:
- *
- ********************************************************************************/
- static void check_spaces_leftright(char *line, int lineno, int ndx1, int ndx2)
- {
- if (ndx1 > 0 && line[ndx1 - 1] != ' ')
- {
- ERROR("Operator/assignment must be preceded with whitespace",
- lineno, ndx1);
- }
- if (line[ndx2 + 1] != '\0' && line[ndx2 + 1] != '\n' && line[ndx2 + 1] != ' ')
- {
- ERROR("Operator/assignment must be followed with whitespace",
- lineno, ndx2);
- }
- }
- /********************************************************************************
- * Name: block_comment_width
- *
- * Description:
- * Get the width of a block comment
- *
- ********************************************************************************/
- static int block_comment_width(char *line)
- {
- int b;
- int e;
- int n;
- /* Skip over any leading whitespace on the line */
- for (b = 0; isspace(line[b]); b++)
- {
- }
- /* Skip over any trailing whitespace at the end of the line */
- for (e = strlen(line) - 1; e >= 0 && isspace(line[e]); e--)
- {
- }
- /* Number of characters on the line */
- n = e - b + 1;
- if (n < 4)
- {
- return 0;
- }
- /* The first line of a block comment starts with "[slash]***" and ends with
- * "***"
- */
- if (strncmp(&line[b], "/***", 4) == 0 &&
- strncmp(&line[e - 2], "***", 3) == 0)
- {
- /* Return the the length of the line up to the final '*' */
- return e + 1;
- }
- /* The last line of a block begins with whitespace then "***" and ends
- * with "***[slash]"
- */
- if (strncmp(&line[b], "***", 3) == 0 &&
- strncmp(&line[e - 3], "***/", 4) == 0)
- {
- /* Return the the length of the line up to the final '*' */
- return e;
- }
- /* But there is also a special single line comment that begins with "[slash]* "
- * and ends with "***[slash]"
- */
- if (strncmp(&line[b], "/*", 2) == 0 &&
- strncmp(&line[e - 3], "***/", 4) == 0)
- {
- /* Return the the length of the line up to the final '*' */
- return e;
- }
- /* Return zero if the line is not the first or last line of a block
- * comment.
- */
- return 0;
- }
- /********************************************************************************
- * Name: get_line_width
- *
- * Description:
- * Get the maximum line width by examining the width of the block comments.
- *
- ********************************************************************************/
- static int get_line_width(FILE *instream)
- {
- char line[LINE_SIZE]; /* The current line being examined */
- int max = 0;
- int min = INT_MAX;
- int lineno = 0;
- int lineno_max = 0;
- int lineno_min = 0;
- int len;
- while (fgets(line, LINE_SIZE, instream))
- {
- lineno++;
- len = block_comment_width(line);
- if (len > 0)
- {
- if (len > max)
- {
- max = len;
- lineno_max = lineno;
- }
- if (len < min)
- {
- min = len;
- lineno_min = lineno;
- }
- }
- }
- if (max < min)
- {
- ERRORFL("No block comments found", g_file_name);
- return DEFAULT_WIDTH;
- }
- else if (max != min)
- {
- ERROR("Block comments have different lengths", lineno_max, max);
- ERROR("Block comments have different lengths", lineno_min, min);
- return DEFAULT_WIDTH;
- }
- return min;
- }
- /********************************************************************************
- * Name: check_section_header
- *
- * Description:
- * Check if the current line holds a section header
- *
- ********************************************************************************/
- static bool check_section_header(const char *line, int lineno)
- {
- int i;
- /* Search g_section_info[] to find a matching section header line */
- for (i = FIRST_SECTION; i <= LAST_SECTION; i++)
- {
- if (strcmp(line, g_section_info[i].name) == 0)
- {
- g_section = (enum section_s)i;
- /* Verify that this section is appropriate for this file type */
- if ((g_file_type & g_section_info[i].ftype) == 0)
- {
- ERROR("Invalid section for this file type", lineno, 3);
- }
- return true;
- }
- }
- return false;
- }
- /********************************************************************************
- * Name: white_prefix
- *
- * Description:
- * Return true if the identifier string begins with a white-listed prefix
- *
- ********************************************************************************/
- static bool white_list(const char *ident, int lineno)
- {
- const char **pptr;
- const char *str;
- for (pptr = g_white_prefix;
- (str = *pptr) != NULL;
- pptr++)
- {
- if (strncmp(ident, str, strlen(str)) == 0)
- {
- return true;
- }
- }
- for (pptr = g_white_list;
- (str = *pptr) != NULL;
- pptr++)
- {
- size_t len = strlen(str);
- if (strncmp(ident, str, len) == 0 &&
- isalnum(ident[len]) == 0)
- {
- return true;
- }
- }
- return false;
- }
- /********************************************************************************
- * Public Functions
- ********************************************************************************/
- int main(int argc, char **argv, char **envp)
- {
- FILE *instream; /* File input stream */
- char line[LINE_SIZE]; /* The current line being examined */
- char buffer[100]; /* Localy format error strings */
- char *lptr; /* Temporary pointer into line[] */
- char *ext; /* Temporary file extension */
- bool btabs; /* True: TAB characters found on the line */
- bool bcrs; /* True: Carriage return found on the line */
- bool bfunctions; /* True: In private or public functions */
- bool bstatm; /* True: This line is beginning of a statement */
- bool bfor; /* True: This line is beginning of a 'for' statement */
- bool bswitch; /* True: Within a switch statement */
- bool bstring; /* True: Within a string */
- bool bquote; /* True: Backslash quoted character next */
- bool bblank; /* Used to verify block comment terminator */
- bool bexternc; /* True: Within 'extern "C"' */
- enum pptype_e ppline; /* > 0: The next line the continuation of a
- * pre-processor command */
- int rhcomment; /* Indentation of Comment to the right of code
- * (-1 -> don't check position) */
- int prevrhcmt; /* Indentation of previous Comment to the right
- * of code (-1 -> don't check position) */
- int lineno; /* Current line number */
- int indent; /* Indentation level */
- int ncomment; /* Comment nesting level on this line */
- int prevncomment; /* Comment nesting level on the previous line */
- int bnest; /* Brace nesting level on this line */
- int prevbnest; /* Brace nesting level on the previous line */
- int dnest; /* Data declaration nesting level on this line */
- int prevdnest; /* Data declaration nesting level on the previous line */
- int pnest; /* Parenthesis nesting level on this line */
- int ppifnest; /* #if nesting level on this line */
- int inasm; /* > 0: Within #ifdef __ASSEMBLY__ */
- int comment_lineno; /* Line on which the last comment was closed */
- int blank_lineno; /* Line number of the last blank line */
- int noblank_lineno; /* A blank line is not needed after this line */
- int lbrace_lineno; /* Line number of last left brace */
- int rbrace_lineno; /* Last line containing a right brace */
- int externc_lineno; /* Last line where 'extern "C"' declared */
- int linelen; /* Length of the line */
- int excess;
- int n;
- int i;
- int c;
- excess = 0;
- while ((c = getopt(argc, argv, ":hv:gm:r:")) != -1)
- {
- switch (c)
- {
- case 'm':
- excess = atoi(optarg);
- if (excess < 1)
- {
- show_usage(argv[0], 1, "Bad value for <excess>.");
- excess = 0;
- }
- break;
- case 'v':
- g_verbose = atoi(optarg);
- if (g_verbose < 0 || g_verbose > 2)
- {
- show_usage(argv[0], 1, "Bad value for <level>.");
- }
- break;
- case 'r':
- g_rangestart[g_rangenumber] = atoi(strtok(optarg, ","));
- g_rangecount[g_rangenumber++] = atoi(strtok(NULL, ","));
- break;
- case 'h':
- show_usage(argv[0], 0, NULL);
- break;
- case ':':
- show_usage(argv[0], 1, "Missing argument.");
- break;
- case '?':
- show_usage(argv[0], 1, "Unrecognized option.");
- break;
- default:
- show_usage(argv[0], 0, NULL);
- break;
- }
- }
- if (optind < argc - 1 || argv[optind] == NULL)
- {
- show_usage(argv[0], 1, "No file name given.");
- }
- /* Resolve the absolute path for the input file */
- if (realpath(argv[optind], g_file_name) == NULL)
- {
- FATALFL("Failed to resolve absolute path.", g_file_name);
- return 1;
- }
- /* Are we parsing a header file? */
- ext = strrchr(g_file_name, '.');
- if (ext == 0)
- {
- }
- else if (strcmp(ext, ".h") == 0)
- {
- g_file_type = C_HEADER;
- }
- else if (strcmp(ext, ".c") == 0)
- {
- g_file_type = C_SOURCE;
- }
- if (g_file_type == UNKNOWN)
- {
- return 0;
- }
- instream = fopen(g_file_name, "r");
- if (!instream)
- {
- FATALFL("Failed to open", g_file_name);
- return 1;
- }
- /* Determine the line width */
- g_maxline = get_line_width(instream) + excess;
- rewind(instream);
- btabs = false; /* True: TAB characters found on the line */
- bcrs = false; /* True: Carriage return found on the line */
- bfunctions = false; /* True: In private or public functions */
- bswitch = false; /* True: Within a switch statement */
- bstring = false; /* True: Within a string */
- bexternc = false; /* True: Within 'extern "C"' */
- ppline = PPLINE_NONE; /* > 0: The next line the continuation of a
- * pre-processor command */
- rhcomment = 0; /* Indentation of Comment to the right of code
- * (-1 -> don't check position) */
- prevrhcmt = 0; /* Indentation of previous Comment to the right
- * of code (-1 -> don't check position) */
- lineno = 0; /* Current line number */
- ncomment = 0; /* Comment nesting level on this line */
- bnest = 0; /* Brace nesting level on this line */
- dnest = 0; /* Data declaration nesting level on this line */
- pnest = 0; /* Parenthesis nesting level on this line */
- ppifnest = 0; /* #if nesting level on this line */
- inasm = 0; /* > 0: Within #ifdef __ASSEMBLY__ */
- comment_lineno = -1; /* Line on which the last comment was closed */
- blank_lineno = -1; /* Line number of the last blank line */
- noblank_lineno = -1; /* A blank line is not needed after this line */
- lbrace_lineno = -1; /* Line number of last left brace */
- rbrace_lineno = -1; /* Last line containing a right brace */
- externc_lineno = -1; /* Last line where 'extern "C"' declared */
- /* Process each line in the input stream */
- while (fgets(line, LINE_SIZE, instream))
- {
- lineno++;
- indent = 0;
- prevbnest = bnest; /* Brace nesting level on the previous line */
- prevdnest = dnest; /* Data declaration nesting level on the
- * previous line */
- prevncomment = ncomment; /* Comment nesting level on the previous line */
- bstatm = false; /* True: This line is beginning of a
- * statement */
- bfor = false; /* REVISIT: Implies for() is all on one line */
- /* If we are not in a comment, then this certainly is not a right-hand
- * comment.
- */
- prevrhcmt = rhcomment;
- if (ncomment <= 0)
- {
- rhcomment = 0;
- }
- /* Check for a blank line */
- for (n = 0; line[n] != '\n' && isspace((int)line[n]); n++)
- {
- }
- if (line[n] == '\n')
- {
- if (n > 0)
- {
- ERROR("Blank line contains whitespace", lineno, 1);
- }
- if (lineno == 1)
- {
- ERROR("File begins with a blank line", 1, 1);
- }
- else if (lineno == blank_lineno + 1)
- {
- ERROR("Too many blank lines", lineno, 1);
- }
- else if (lineno == lbrace_lineno + 1)
- {
- ERROR("Blank line follows left brace", lineno, 1);
- }
- blank_lineno = lineno;
- continue;
- }
- else /* This line is non-blank */
- {
- /* Check for a missing blank line after a comment */
- if (lineno == comment_lineno + 1)
- {
- /* No blank line should be present if the current line contains
- * a right brace, a pre-processor line, the start of another
- * comment.
- *
- * REVISIT: Generates a false alarm if the current line is also
- * a comment. Generally it is acceptable for one comment to
- * follow another with no space separation.
- *
- * REVISIT: prevrhcmt is tested to case the preceding line
- * contained comments to the right of the code. In such cases,
- * the comments are normally aligned and do not follow normal
- * indentation rules. However, this code will generate a false
- * alarm if the comments are aligned to the right BUT the
- * preceding line has no comment.
- */
- if (line[n] != '}' && line[n] != '#' && prevrhcmt == 0)
- {
- ERROR("Missing blank line after comment", comment_lineno,
- 1);
- }
- }
- /* Files must begin with a comment (the file header).
- * REVISIT: Logically, this belongs in the STEP 2 operations
- * below.
- */
- if (lineno == 1 && (line[n] != '/' || line[n + 1] != '*'))
- {
- ERROR("Missing file header comment block", lineno, 1);
- }
- if (lineno == 2)
- {
- if (line[n] == '*' && line[n + 1] == '\n')
- {
- ERROR("Missing relative file path in file header", lineno,
- n);
- }
- else if (isspace(line[n + 2]))
- {
- ERROR("Too many whitespaces before relative file path",
- lineno, n);
- }
- else
- {
- const char *apps_dir = "apps/";
- const size_t apps_len = strlen(apps_dir);
- size_t offset;
- #ifdef TOPDIR
- /* TOPDIR macro contains the absolute path to the "nuttx"
- * root directory. It should have been defined via Makefile
- * and it is required to accurately evaluate the relative
- * path contained in the file header. Otherwise, skip this
- * verification.
- */
- char *basedir = strstr(g_file_name, TOPDIR);
- if (basedir != NULL)
- {
- /* Add 1 to the offset for the slash character */
- offset = strlen(TOPDIR) + 1;
- /* Duplicate the line from the beginning of the
- * relative file path, removing the '\n' at the end of
- * the string.
- */
- char *line_dup = strndup(&line[n + 2],
- strlen(&line[n + 2]) - 1);
- if (strcmp(line_dup, basedir + offset) != 0)
- {
- ERROR("Relative file path does not match actual file",
- lineno, n);
- }
- free(line_dup);
- }
- else if (strncmp(&line[n + 2], apps_dir, apps_len) != 0)
- {
- /* g_file_name neither belongs to "nuttx" repository
- * nor begins with the root dir of the other
- * repository (e.g. "apps/")
- */
- ERROR("Path relative to repository other than \"nuttx\" "
- "must begin with the root directory", lineno, n);
- }
- else
- {
- #endif
- offset = 0;
- if (strncmp(&line[n + 2], apps_dir, apps_len) == 0)
- {
- /* Input file belongs to the "apps" repository */
- /* Calculate the offset to the first directory
- * after the "apps/" folder.
- */
- offset += apps_len;
- }
- /* Duplicate the line from the beginning of the
- * relative file path, removing the '\n' at the end of
- * the string.
- */
- char *line_dup = strndup(&line[n + 2],
- strlen(&line[n + 2]) - 1);
- ssize_t base =
- strlen(g_file_name) - strlen(&line_dup[offset]);
- if (base < 0 ||
- (base != 0 && g_file_name[base - 1] != '/') ||
- strcmp(&g_file_name[base], &line_dup[offset]) != 0)
- {
- ERROR("Relative file path does not match actual file",
- lineno, n);
- }
- free(line_dup);
- #ifdef TOPDIR
- }
- #endif
- }
- }
- /* Check for a blank line following a right brace */
- if (bfunctions && lineno == rbrace_lineno + 1)
- {
- /* Check if this line contains a right brace. A right brace
- * must be followed by 'else', 'while', 'break', a blank line,
- * another right brace, or a pre-processor directive like #endif
- */
- if (dnest == 0 &&
- strchr(line, '}') == NULL && line[n] != '#' &&
- strncmp(&line[n], "else", 4) != 0 &&
- strncmp(&line[n], "while", 5) != 0 &&
- strncmp(&line[n], "break", 5) != 0)
- {
- ERROR("Right brace must be followed by a blank line",
- rbrace_lineno, n + 1);
- }
- /* If the right brace is followed by a pre-processor command
- * like #endif (but not #else or #elif), then set the right
- * brace line number to the line number of the pre-processor
- * command (it then must be followed by a blank line)
- */
- if (line[n] == '#')
- {
- int ii;
- for (ii = n + 1; line[ii] != '\0' && isspace(line[ii]); ii++)
- {
- }
- if (strncmp(&line[ii], "else", 4) != 0 &&
- strncmp(&line[ii], "elif", 4) != 0)
- {
- rbrace_lineno = lineno;
- }
- }
- }
- }
- /* STEP 1: Find the indentation level and the start of real stuff on
- * the line.
- */
- for (n = 0; line[n] != '\n' && isspace((int)line[n]); n++)
- {
- switch (line[n])
- {
- case ' ':
- {
- indent++;
- }
- break;
- case '\t':
- {
- if (!btabs)
- {
- ERROR("TABs found. First detected", lineno, n);
- btabs = true;
- }
- indent = (indent + 4) & ~3;
- }
- break;
- case '\r':
- {
- if (!bcrs)
- {
- ERROR("Carriage returns found. "
- "First detected", lineno, n);
- bcrs = true;
- }
- }
- break;
- default:
- {
- snprintf(buffer, sizeof(buffer),
- "Unexpected white space character %02x found",
- line[n]);
- ERROR(buffer, lineno, n);
- }
- break;
- }
- }
- /* STEP 2: Detect some certain start of line conditions */
- /* Skip over pre-processor lines (or continuations of pre-processor
- * lines as indicated by ppline)
- */
- if (line[indent] == '#' || ppline != PPLINE_NONE)
- {
- int len;
- int ii;
- /* Suppress error for comment following conditional compilation */
- noblank_lineno = lineno;
- /* Check pre-processor commands if this is not a continuation
- * line.
- */
- ii = indent + 1;
- if (ppline == PPLINE_NONE)
- {
- /* Skip to the pre-processor command following the '#' */
- while (line[ii] != '\0' && isspace(line[ii]))
- {
- ii++;
- }
- if (line[ii] != '\0')
- {
- /* Make sure that pre-processor definitions are all in
- * the pre-processor definitions section.
- */
- ppline = PPLINE_OTHER;
- if (strncmp(&line[ii], "define", 6) == 0)
- {
- ppline = PPLINE_DEFINE;
- if (g_section != PRE_PROCESSOR_DEFINITIONS)
- {
- /* A complication is the header files always have
- * the idempotence guard definitions before the
- * "Pre-processor Definitions section".
- */
- if (g_section == NO_SECTION &&
- g_file_type != C_HEADER)
- {
- /* Only a warning because there is some usage
- * of define outside the Pre-processor
- * Definitions section which is justifiable.
- * Should be manually checked.
- */
- WARN("#define outside of 'Pre-processor "
- "Definitions' section",
- lineno, ii);
- }
- }
- }
- /* Make sure that files are included only in the Included
- * Files section.
- */
- else if (strncmp(&line[ii], "include", 7) == 0)
- {
- if (g_section != INCLUDED_FILES)
- {
- /* Only a warning because there is some usage of
- * include outside the Included Files section
- * which may be is justifiable. Should be
- * manually checked.
- */
- WARN("#include outside of 'Included Files' "
- "section",
- lineno, ii);
- }
- }
- else if (strncmp(&line[ii], "if", 2) == 0)
- {
- ppifnest++;
- ppline = PPLINE_IF;
- ii += 2;
- }
- else if (strncmp(&line[ii], "elif", 4) == 0)
- {
- if (ppifnest == inasm)
- {
- inasm = 0;
- }
- ppline = PPLINE_ELIF;
- ii += 4;
- }
- else if (strncmp(&line[ii], "else", 4) == 0)
- {
- if (ppifnest == inasm)
- {
- inasm = 0;
- }
- ppline = PPLINE_ELSE;
- }
- else if (strncmp(&line[ii], "endif", 4) == 0)
- {
- if (ppifnest == inasm)
- {
- inasm = 0;
- }
- ppifnest--;
- ppline = PPLINE_ENDIF;
- }
- }
- }
- if (ppline == PPLINE_IF || ppline == PPLINE_ELIF)
- {
- int bdef = 0;
- if (strncmp(&line[ii], "def", 3) == 0)
- {
- bdef = 1;
- ii += 3;
- }
- else
- {
- while (line[ii] != '\0' && isspace(line[ii]))
- {
- ii++;
- }
- if (strncmp(&line[ii], "defined", 7) == 0)
- {
- bdef = 1;
- ii += 7;
- }
- }
- if (bdef)
- {
- while (line[ii] != '\0' &&
- (isspace(line[ii]) || line[ii] == '('))
- {
- ii++;
- }
- if (strncmp(&line[ii], "__ASSEMBLY__", 12) == 0)
- {
- inasm = ppifnest;
- }
- }
- }
- /* Check if the next line will be a continuation of the pre-
- * processor command.
- */
- len = strlen(&line[indent]) + indent - 1;
- if (line[len] == '\n')
- {
- len--;
- }
- /* Propagate rhcomment over preprocessor lines Issue #120 */
- if (prevrhcmt != 0)
- {
- /* Don't check position */
- rhcomment = -1;
- }
- lptr = strstr(line, "/*");
- if (lptr != NULL)
- {
- n = lptr - &line[0];
- if (line[n + 2] == '\n')
- {
- ERROR("C comment opening on separate line", lineno, n);
- }
- else if (!isspace((int)line[n + 2]) && line[n + 2] != '*')
- {
- ERROR("Missing space after opening C comment", lineno, n);
- }
- if (strstr(lptr, "*/") == NULL)
- {
- /* Increment the count of nested comments */
- ncomment++;
- }
- if (ppline == PPLINE_DEFINE)
- {
- rhcomment = n;
- if (prevrhcmt > 0 && n != prevrhcmt)
- {
- rhcomment = prevrhcmt;
- WARN("Wrong column position of comment right of code",
- lineno, n);
- }
- }
- else
- {
- /* Signal rhcomment, but ignore position */
- rhcomment = -1;
- if (ncomment > 0 &&
- (ppline == PPLINE_IF ||
- ppline == PPLINE_ELSE ||
- ppline == PPLINE_ELIF))
- {
- /* in #if... and #el... */
- ERROR("No multiline comment right of code allowed here",
- lineno, n);
- }
- }
- }
- if (line[len] != '\\' || ncomment > 0)
- {
- ppline = PPLINE_NONE;
- }
- continue;
- }
- /* Check for a single line comment */
- linelen = strlen(line);
- if (linelen >= 5) /* Minimum is slash, star, star, slash, newline */
- {
- lptr = strstr(line, "*/");
- if (line[indent] == '/' && line[indent + 1] == '*' &&
- lptr - line == linelen - 3)
- {
- /* If preceding comments were to the right of code, then we can
- * assume that there is a columnar alignment of columns that do
- * no follow the usual alignment. So the rhcomment flag
- * should propagate.
- */
- rhcomment = prevrhcmt;
- /* Check if there should be a blank line before the comment */
- if (lineno > 1 &&
- comment_lineno != lineno - 1 &&
- blank_lineno != lineno - 1 &&
- noblank_lineno != lineno - 1 &&
- rhcomment == 0)
- {
- /* TODO: This generates a false alarm if preceded
- * by a label.
- */
- ERROR("Missing blank line before comment found", lineno, 1);
- }
- /* 'comment_lineno 'holds the line number of the last closing
- * comment. It is used only to verify that the comment is
- * followed by a blank line.
- */
- comment_lineno = lineno;
- }
- }
- /* Check for the comment block indicating the beginning of a new file
- * section.
- */
- if (check_section_header(line, lineno))
- {
- if (g_section == PRIVATE_FUNCTIONS || g_section == PUBLIC_FUNCTIONS)
- {
- bfunctions = true; /* Latched */
- }
- }
- /* Check for some kind of declaration.
- * REVISIT: The following logic fails for any non-standard types.
- * REVISIT: Terminator after keyword might not be a space. Might be
- * a newline, for example. struct and unions are often unnamed, for
- * example.
- */
- else if (inasm == 0)
- {
- if (strncmp(&line[indent], "auto ", 5) == 0 ||
- strncmp(&line[indent], "bool ", 5) == 0 ||
- strncmp(&line[indent], "char ", 5) == 0 ||
- strncmp(&line[indent], "CODE ", 5) == 0 ||
- strncmp(&line[indent], "const ", 6) == 0 ||
- strncmp(&line[indent], "double ", 7) == 0 ||
- strncmp(&line[indent], "struct ", 7) == 0 ||
- strncmp(&line[indent], "struct\n", 7) == 0 || /* May be unnamed */
- strncmp(&line[indent], "enum ", 5) == 0 ||
- strncmp(&line[indent], "extern ", 7) == 0 ||
- strncmp(&line[indent], "EXTERN ", 7) == 0 ||
- strncmp(&line[indent], "FAR ", 4) == 0 ||
- strncmp(&line[indent], "float ", 6) == 0 ||
- strncmp(&line[indent], "int ", 4) == 0 ||
- strncmp(&line[indent], "int16_t ", 8) == 0 ||
- strncmp(&line[indent], "int32_t ", 8) == 0 ||
- strncmp(&line[indent], "long ", 5) == 0 ||
- strncmp(&line[indent], "off_t ", 6) == 0 ||
- strncmp(&line[indent], "register ", 9) == 0 ||
- strncmp(&line[indent], "short ", 6) == 0 ||
- strncmp(&line[indent], "signed ", 7) == 0 ||
- strncmp(&line[indent], "size_t ", 7) == 0 ||
- strncmp(&line[indent], "ssize_t ", 8) == 0 ||
- strncmp(&line[indent], "static ", 7) == 0 ||
- strncmp(&line[indent], "time_t ", 7) == 0 ||
- strncmp(&line[indent], "typedef ", 8) == 0 ||
- strncmp(&line[indent], "uint8_t ", 8) == 0 ||
- strncmp(&line[indent], "uint16_t ", 9) == 0 ||
- strncmp(&line[indent], "uint32_t ", 9) == 0 ||
- strncmp(&line[indent], "union ", 6) == 0 ||
- strncmp(&line[indent], "union\n", 6) == 0 || /* May be unnamed */
- strncmp(&line[indent], "unsigned ", 9) == 0 ||
- strncmp(&line[indent], "void ", 5) == 0 ||
- strncmp(&line[indent], "volatile ", 9) == 0)
- {
- /* Check if this is extern "C"; We don't typically indent
- * following this.
- */
- if (strncmp(&line[indent], "extern \"C\"", 10) == 0)
- {
- externc_lineno = lineno;
- }
- /* bfunctions: True: Processing private or public functions.
- * bnest: Brace nesting level on this line
- * dnest: Data declaration nesting level on this line
- */
- /* REVISIT: Also picks up function return types */
- /* REVISIT: Logic problem for nested data/function declarations */
- if ((!bfunctions || bnest > 0) && dnest == 0)
- {
- dnest = 1;
- }
- /* Check for multiple definitions of variables on the line.
- * Ignores declarations within parentheses which are probably
- * formal parameters.
- */
- if (pnest == 0)
- {
- int tmppnest;
- /* Note, we have not yet parsed each character on the line so
- * a comma have have been be preceded by '(' on the same line.
- * We will have parse up to any comma to see if that is the
- * case.
- */
- for (i = indent, tmppnest = 0;
- line[i] != '\n' && line[i] != '\0';
- i++)
- {
- if (tmppnest == 0 && line[i] == ',')
- {
- ERROR("Multiple data definitions", lineno, i + 1);
- break;
- }
- else if (line[i] == '(')
- {
- tmppnest++;
- }
- else if (line[i] == ')')
- {
- if (tmppnest < 1)
- {
- /* We should catch this later */
- break;
- }
- tmppnest--;
- }
- else if (line[i] == ';')
- {
- /* Break out if the semicolon terminates the
- * declaration is found. Avoids processing any
- * righthand comments in most cases.
- */
- break;
- }
- }
- }
- }
- /* Check for a keyword indicating the beginning of a statement.
- * REVISIT: This, obviously, will not detect statements that do not
- * begin with a C keyword (such as assignment statements).
- */
- else if (strncmp(&line[indent], "break ", 6) == 0 ||
- strncmp(&line[indent], "case ", 5) == 0 ||
- #if 0 /* Part of switch */
- strncmp(&line[indent], "case ", 5) == 0 ||
- #endif
- strncmp(&line[indent], "continue ", 9) == 0 ||
- #if 0 /* Part of switch */
- strncmp(&line[indent], "default ", 8) == 0 ||
- #endif
- strncmp(&line[indent], "do ", 3) == 0 ||
- strncmp(&line[indent], "else ", 5) == 0 ||
- strncmp(&line[indent], "goto ", 5) == 0 ||
- strncmp(&line[indent], "if ", 3) == 0 ||
- strncmp(&line[indent], "return ", 7) == 0 ||
- #if 0 /* Doesn't follow pattern */
- strncmp(&line[indent], "switch ", 7) == 0 ||
- #endif
- strncmp(&line[indent], "while ", 6) == 0)
- {
- bstatm = true;
- }
- /* Spacing works a little differently for and switch statements */
- else if (strncmp(&line[indent], "for ", 4) == 0)
- {
- bfor = true;
- bstatm = true;
- }
- else if (strncmp(&line[indent], "switch ", 7) == 0)
- {
- bswitch = true;
- }
- /* Also check for C keywords with missing white space */
- else if (strncmp(&line[indent], "do(", 3) == 0 ||
- strncmp(&line[indent], "if(", 3) == 0 ||
- strncmp(&line[indent], "while(", 6) == 0)
- {
- ERROR("Missing whitespace after keyword", lineno, n);
- bstatm = true;
- }
- else if (strncmp(&line[indent], "for(", 4) == 0)
- {
- ERROR("Missing whitespace after keyword", lineno, n);
- bfor = true;
- bstatm = true;
- }
- else if (strncmp(&line[indent], "switch(", 7) == 0)
- {
- ERROR("Missing whitespace after keyword", lineno, n);
- bswitch = true;
- }
- }
- /* STEP 3: Parse each character on the line */
- bquote = false; /* True: Backslash quoted character next */
- bblank = true; /* Used to verify block comment terminator */
- for (; line[n] != '\n' && line[n] != '\0'; n++)
- {
- /* Report any use of non-standard white space characters */
- if (isspace(line[n]))
- {
- if (line[n] == '\t')
- {
- if (!btabs)
- {
- ERROR("TABs found. First detected", lineno, n);
- btabs = true;
- }
- }
- else if (line[n] == '\r')
- {
- if (!bcrs)
- {
- ERROR("Carriage returns found. "
- "First detected", lineno, n);
- bcrs = true;
- }
- }
- else if (line[n] != ' ')
- {
- snprintf(buffer, sizeof(buffer),
- "Unexpected white space character %02x found",
- line[n]);
- ERROR(buffer, lineno, n);
- }
- }
- /* Skip over identifiers */
- if (ncomment == 0 && !bstring && (line[n] == '_' || isalpha(line[n])))
- {
- bool have_upper = false;
- bool have_lower = false;
- int ident_index = n;
- /* Parse over the identifier. Check if it contains mixed upper-
- * and lower-case characters.
- */
- do
- {
- have_upper |= isupper(line[n]);
- /* The coding standard provides for some exceptions of lower
- * case characters in pre-processor strings:
- *
- * IPv[4|6] as an IP version number
- * ICMPv6 as an ICMP version number
- * IGMPv2 as an IGMP version number
- * [0-9]p[0-9] as a decimal point
- * d[0-9] as a divisor
- * Hz for frequencies (including KHz, MHz, etc.)
- */
- if (!have_lower && islower(line[n]))
- {
- switch (line[n])
- {
- /* A sequence containing 'v' may occur at the
- * beginning of the identifier.
- */
- case 'v':
- if (n > 1 &&
- line[n - 2] == 'I' &&
- line[n - 1] == 'P' &&
- (line[n + 1] == '4' ||
- line[n + 1] == '6'))
- {
- }
- else if (n > 3 &&
- line[n - 4] == 'I' &&
- line[n - 3] == 'C' &&
- line[n - 2] == 'M' &&
- line[n - 1] == 'P' &&
- line[n + 1] == '6')
- {
- }
- else if (n > 3 &&
- line[n - 4] == 'I' &&
- line[n - 3] == 'G' &&
- line[n - 2] == 'M' &&
- line[n - 1] == 'P' &&
- line[n + 1] == '2')
- {
- }
- else
- {
- have_lower = true;
- }
- break;
- /* Sequences containing 'p', 'd', or 'z' must have
- * been preceded by upper case characters.
- */
- case 'p':
- if (!have_upper || n < 1 ||
- !isdigit(line[n - 1]) ||
- !isdigit(line[n + 1]))
- {
- have_lower = true;
- }
- break;
- case 'd':
- if (!have_upper || !isdigit(line[n + 1]))
- {
- have_lower = true;
- }
- break;
- case 'z':
- if (!have_upper || n < 1 ||
- line[n - 1] != 'H')
- {
- have_lower = true;
- }
- break;
- break;
- default:
- have_lower = true;
- break;
- }
- }
- n++;
- }
- while (line[n] == '_' || isalnum(line[n]));
- /* Check for mixed upper and lower case */
- if (have_upper && have_lower)
- {
- /* Ignore symbols that begin with white-listed prefixes */
- if (white_list(&line[ident_index], lineno))
- {
- /* No error */
- }
- /* Special case hex constants. These will look like
- * identifiers starting with 'x' or 'X' but preceded
- * with '0'
- */
- else if (ident_index < 1 ||
- (line[ident_index] != 'x' &&
- line[ident_index] != 'X') ||
- line[ident_index - 1] != '0')
- {
- ERROR("Mixed case identifier found",
- lineno, ident_index);
- }
- else if (have_upper)
- {
- ERROR("Upper case hex constant found",
- lineno, ident_index);
- }
- }
- /* Check if the identifier is the last thing on the line */
- if (line[n] == '\n' || line[n] == '\0')
- {
- break;
- }
- }
- /* Handle comments */
- if (line[n] == '/' && !bstring)
- {
- /* Check for start of a C comment */
- if (line[n + 1] == '*')
- {
- if (line[n + 2] == '\n')
- {
- ERROR("C comment opening on separate line", lineno, n);
- }
- else if (!isspace((int)line[n + 2]) && line[n + 2] != '*')
- {
- ERROR("Missing space after opening C comment", lineno, n);
- }
- /* Increment the count of nested comments */
- ncomment++;
- /* If there is anything to the left of the left brace, then
- * this must be a comment to the right of code.
- * Also if preceding comments were to the right of code, then
- * we can assume that there is a columnar alignment of columns
- * that do no follow the usual alignment. So the rhcomment
- * flag should propagate.
- */
- if (prevrhcmt == 0)
- {
- if (n != indent)
- {
- rhcomment = n;
- }
- }
- else
- {
- rhcomment = n;
- if (prevrhcmt > 0 && n != prevrhcmt)
- {
- rhcomment = prevrhcmt;
- if (n != indent)
- {
- WARN("Wrong column position of "
- "comment right of code", lineno, n);
- }
- else
- {
- ERROR("Wrong column position or missing "
- "blank line before comment", lineno, n);
- }
- }
- }
- n++;
- continue;
- }
- /* Check for end of a C comment */
- else if (n > 0 && line[n - 1] == '*')
- {
- if (n < 2)
- {
- ERROR("Closing C comment not indented", lineno, n);
- }
- else if (!isspace((int)line[n - 2]) && line[n - 2] != '*')
- {
- ERROR("Missing space before closing C comment", lineno,
- n);
- }
- /* Check for block comments that are not on a separate line.
- * This would be the case if we are we are within a comment
- * that did not start on this line and the current line is
- * not blank up to the point where the comment was closed.
- */
- if (prevncomment > 0 && !bblank && rhcomment == 0)
- {
- ERROR("Block comment terminator must be on a "
- "separate line", lineno, n);
- }
- #if 0
- /* REVISIT: Generates false alarms when portions of an
- * expression are commented out within the expression.
- */
- if (line[n + 1] != '\n')
- {
- ERROR("Garbage on line after C comment", lineno, n);
- }
- #endif
- /* Handle nested comments */
- if (ncomment > 0)
- {
- /* Remember the line number of the line containing the
- * closing of the outermost comment.
- */
- if (--ncomment == 0)
- {
- /* 'comment_lineno 'holds the line number of the
- * last closing comment. It is used only to
- * verify that the comment is followed by a blank
- * line.
- */
- comment_lineno = lineno;
- /* Note that rhcomment must persist to support a
- * later test for comment alignment. We will fix
- * that at the top of the loop when ncomment == 0.
- */
- }
- }
- else
- {
- /* Note that rhcomment must persist to support a later
- * test for comment alignment. We will will fix that
- * at the top of the loop when ncomment == 0.
- */
- ncomment = 0;
- ERROR("Closing without opening comment", lineno, n);
- }
- n++;
- continue;
- }
- /* Check for C++ style comments */
- else if (line[n + 1] == '/')
- {
- /* Check for URI schemes, e.g. "http://" or "https://" */
- if (n == 0 || strncmp(&line[n - 1], "://", 3) != 0)
- {
- ERROR("C++ style comment", lineno, n);
- n++;
- continue;
- }
- }
- }
- /* Check if the line is blank so far. This is only used to
- * to verify the the closing of a block comment is on a separate
- * line. So we also need to treat '*' as a 'blank'.
- */
- if (!isblank(line[n]) && line[n] != '*')
- {
- bblank = false;
- }
- /* Check for a string... ignore if we are in the middle of a
- * comment.
- */
- if (ncomment == 0)
- {
- /* Backslash quoted character */
- if (line[n] == '\\')
- {
- bquote = true;
- n++;
- }
- /* Check for quoted characters: \" in string */
- if (line[n] == '"' && !bquote)
- {
- bstring = !bstring;
- }
- bquote = false;
- }
- /* The rest of the line is only examined of we are not in a comment,
- * in a string or in assembly.
- *
- * REVISIT: Should still check for whitespace at the end of the
- * line.
- */
- if (ncomment == 0 && !bstring && inasm == 0)
- {
- switch (line[n])
- {
- /* Handle logic nested with curly braces */
- case '{':
- {
- if (n > indent)
- {
- /* REVISIT: dnest is always > 0 here if bfunctions ==
- * false.
- */
- if (dnest == 0 || !bfunctions || lineno == rbrace_lineno)
- {
- ERROR("Left bracket not on separate line", lineno,
- n);
- }
- }
- else if (line[n + 1] != '\n')
- {
- if (dnest == 0)
- {
- ERROR("Garbage follows left bracket", lineno, n);
- }
- }
- bnest++;
- if (dnest > 0)
- {
- dnest++;
- }
- /* Check if we are within 'extern "C"', we don't
- * normally indent in that case because the 'extern "C"'
- * is conditioned on __cplusplus.
- */
- if (lineno == externc_lineno ||
- lineno - 1 == externc_lineno)
- {
- bexternc = true;
- }
- /* Suppress error for comment following a left brace */
- noblank_lineno = lineno;
- lbrace_lineno = lineno;
- }
- break;
- case '}':
- {
- /* Decrement the brace nesting level */
- if (bnest < 1)
- {
- ERROR("Unmatched right brace", lineno, n);
- }
- else
- {
- bnest--;
- if (bnest < 1)
- {
- bnest = 0;
- bswitch = false;
- }
- }
- /* Decrement the declaration nesting level */
- if (dnest < 3)
- {
- dnest = 0;
- bexternc = false;
- }
- else
- {
- dnest--;
- }
- /* The right brace should be on a separate line */
- if (n > indent)
- {
- if (dnest == 0)
- {
- ERROR("Right bracket not on separate line",
- lineno, n);
- }
- }
- /* Check for garbage following the left brace */
- if (line[n + 1] != '\n' &&
- line[n + 1] != ',' &&
- line[n + 1] != ';')
- {
- int sndx = n + 1;
- bool whitespace = false;
- /* Skip over spaces */
- while (line[sndx] == ' ')
- {
- sndx++;
- }
- /* One possibility is that the right bracket is
- * followed by an identifier then a semi-colon.
- * Comma is possible to but would be a case of
- * multiple declaration of multiple instances.
- */
- if (line[sndx] == '_' || isalpha(line[sndx]))
- {
- int endx = sndx;
- /* Skip to the end of the identifier. Checking
- * for mixed case identifiers will be done
- * elsewhere.
- */
- while (line[endx] == '_' ||
- isalnum(line[endx]))
- {
- endx++;
- }
- /* Skip over spaces */
- while (line[endx] == ' ')
- {
- whitespace = true;
- endx++;
- }
- /* Handle according to what comes after the
- * identifier.
- */
- if (strncmp(&line[sndx], "while", 5) == 0)
- {
- ERROR("'while' must be on a separate line",
- lineno, sndx);
- }
- else if (line[endx] == ',')
- {
- ERROR("Multiple data definitions on line",
- lineno, endx);
- }
- else if (line[endx] == ';')
- {
- if (whitespace)
- {
- ERROR("Space precedes semi-colon",
- lineno, endx);
- }
- }
- else if (line[endx] == '=')
- {
- /* There's a struct initialization following */
- check_spaces_leftright(line, lineno, endx, endx);
- dnest = 1;
- }
- else
- {
- ERROR("Garbage follows right bracket",
- lineno, n);
- }
- }
- else
- {
- ERROR("Garbage follows right bracket", lineno, n);
- }
- }
- /* The right brace should not be preceded with a a blank
- * line.
- */
- if (lineno == blank_lineno + 1)
- {
- ERROR("Blank line precedes right brace at line",
- lineno, 1);
- }
- rbrace_lineno = lineno;
- }
- break;
- /* Handle logic with parentheses */
- case '(':
- {
- /* Increase the parenthetical nesting level */
- pnest++;
- /* Check for inappropriate space around parentheses */
- if (line[n + 1] == ' ') /* && !bfor */
- {
- ERROR("Space follows left parenthesis", lineno, n);
- }
- }
- break;
- case ')':
- {
- /* Decrease the parenthetical nesting level */
- if (pnest < 1)
- {
- ERROR("Unmatched right parentheses", lineno, n);
- pnest = 0;
- }
- else
- {
- pnest--;
- }
- /* Allow ')' as first thing on the line (n == indent)
- * Allow "for (xx; xx; )" (bfor == true)
- */
- if (n > 0 && n != indent && line[n - 1] == ' ' && !bfor)
- {
- ERROR("Space precedes right parenthesis", lineno, n);
- }
- }
- break;
- /* Check for inappropriate space around square brackets */
- case '[':
- {
- if (line[n + 1] == ' ')
- {
- ERROR("Space follows left bracket", lineno, n);
- }
- }
- break;
- case ']':
- {
- if (n > 0 && line[n - 1] == ' ')
- {
- ERROR("Space precedes right bracket", lineno, n);
- }
- }
- break;
- /* Semi-colon may terminate a declaration */
- case ';':
- {
- if (!isspace((int)line[n + 1]))
- {
- ERROR("Missing whitespace after semicolon", lineno, n);
- }
- /* Semicolon terminates a declaration/definition if there
- * was no left curly brace (i.e., dnest is only 1).
- */
- if (dnest == 1)
- {
- dnest = 0;
- }
- }
- break;
- /* Semi-colon may terminate a declaration */
- case ',':
- {
- if (!isspace((int)line[n + 1]))
- {
- ERROR("Missing whitespace after comma", lineno, n);
- }
- }
- break;
- /* Skip over character constants */
- case '\'':
- {
- int endndx = n + 2;
- if (line[n + 1] != '\n' && line[n + 1] != '\0')
- {
- if (line[n + 1] == '\\')
- {
- for (;
- line[endndx] != '\n' &&
- line[endndx] != '\0' &&
- line[endndx] != '\'';
- endndx++);
- }
- n = endndx + 1;
- }
- }
- break;
- /* Check for space around various operators */
- case '-':
- /* ->, -- */
- if (line[n + 1] == '>' || line[n + 1] == '-')
- {
- n++;
- }
- /* -= */
- else if (line[n + 1] == '=')
- {
- check_spaces_leftright(line, lineno, n, n + 1);
- n++;
- }
- /* Scientific notation with a negative exponent (eg. 10e-10)
- * REVISIT: This fails for cases where the variable name
- * ends with 'e' preceded by a digit:
- * a = abc1e-10;
- * a = ABC1E-10;
- */
- else if ((line[n - 1] == 'e' || line[n - 1] == 'E') &&
- isdigit(line[n + 1]) && isdigit(line[n - 2]))
- {
- n++;
- }
- else
- {
- /* '-' may function as a unary operator and snuggle
- * on the left.
- */
- check_spaces_left(line, lineno, n);
- }
- break;
- case '+':
- /* ++ */
- if (line[n + 1] == '+')
- {
- n++;
- }
- /* += */
- else if (line[n + 1] == '=')
- {
- check_spaces_leftright(line, lineno, n, n + 1);
- n++;
- }
- else
- {
- /* '+' may function as a unary operator and snuggle
- * on the left.
- */
- check_spaces_left(line, lineno, n);
- }
- break;
- case '&':
- /* &<variable> OR &(<expression>) */
- if (isalpha((int)line[n + 1]) || line[n + 1] == '_' ||
- line[n + 1] == '(')
- {
- }
- /* &&, &= */
- else if (line[n + 1] == '=' || line[n + 1] == '&')
- {
- check_spaces_leftright(line, lineno, n, n + 1);
- n++;
- }
- else
- {
- check_spaces_leftright(line, lineno, n, n);
- }
- break;
- case '/':
- /* C comment terminator */
- if (line[n - 1] == '*')
- {
- n++;
- }
- /* C++-style comment */
- else if (line[n + 1] == '/')
- {
- /* Check for "http://" or "https://" */
- if ((n < 5 || strncmp(&line[n - 5], "http://", 7) != 0) &&
- (n < 6 || strncmp(&line[n - 6], "https://", 8) != 0))
- {
- ERROR("C++ style comment on at %d:%d\n",
- lineno, n);
- }
- n++;
- }
- /* /= */
- else if (line[n + 1] == '=')
- {
- check_spaces_leftright(line, lineno, n, n + 1);
- n++;
- }
- /* Division operator */
- else
- {
- check_spaces_leftright(line, lineno, n, n);
- }
- break;
- case '*':
- /* *\/, ** */
- if (line[n] == '*' &&
- (line[n + 1] == '/' ||
- line[n + 1] == '*'))
- {
- n++;
- break;
- }
- /* *<variable>, *(<expression>) */
- else if (isalpha((int)line[n + 1]) ||
- line[n + 1] == '_' ||
- line[n + 1] == '(')
- {
- break;
- }
- /* (<type> *) */
- else if (line[n + 1] == ')')
- {
- /* REVISIT: This gives false alarms on syntax like *--ptr */
- if (line[n - 1] != ' ')
- {
- ERROR("Operator/assignment must be preceded "
- "with whitespace", lineno, n);
- }
- break;
- }
- /* *= */
- else if (line[n + 1] == '=')
- {
- check_spaces_leftright(line, lineno, n, n + 1);
- n++;
- }
- else
- {
- /* A single '*' may be an binary operator, but
- * it could also be a unary operator when used to deference
- * a pointer.
- */
- check_spaces_left(line, lineno, n);
- }
- break;
- case '%':
- /* %= */
- if (line[n + 1] == '=')
- {
- check_spaces_leftright(line, lineno, n, n + 1);
- n++;
- }
- else
- {
- check_spaces_leftright(line, lineno, n, n);
- }
- break;
- case '<':
- /* <=, <<, <<= */
- if (line[n + 1] == '=')
- {
- check_spaces_leftright(line, lineno, n, n + 1);
- n++;
- }
- else if (line[n + 1] == '<')
- {
- if (line[n + 2] == '=')
- {
- check_spaces_leftright(line, lineno, n, n + 2);
- n += 2;
- }
- else
- {
- check_spaces_leftright(line, lineno, n, n + 1);
- n++;
- }
- }
- else
- {
- check_spaces_leftright(line, lineno, n, n);
- }
- break;
- case '>':
- /* >=, >>, >>= */
- if (line[n + 1] == '=')
- {
- check_spaces_leftright(line, lineno, n, n + 1);
- n++;
- }
- else if (line[n + 1] == '>')
- {
- if (line[n + 2] == '=')
- {
- check_spaces_leftright(line, lineno, n, n + 2);
- n += 2;
- }
- else
- {
- check_spaces_leftright(line, lineno, n, n + 1);
- n++;
- }
- }
- else
- {
- check_spaces_leftright(line, lineno, n, n);
- }
- break;
- case '|':
- /* |=, || */
- if (line[n + 1] == '=')
- {
- check_spaces_leftright(line, lineno, n, n + 1);
- n++;
- }
- else if (line[n + 1] == '|')
- {
- check_spaces_leftright(line, lineno, n, n + 1);
- n++;
- }
- else
- {
- check_spaces_leftright(line, lineno, n, n);
- }
- break;
- case '^':
- /* ^= */
- if (line[n + 1] == '=')
- {
- check_spaces_leftright(line, lineno, n, n + 1);
- n++;
- }
- else
- {
- check_spaces_leftright(line, lineno, n, n);
- }
- break;
- case '=':
- /* == */
- if (line[n + 1] == '=')
- {
- check_spaces_leftright(line, lineno, n, n + 1);
- n++;
- }
- else
- {
- check_spaces_leftright(line, lineno, n, n);
- }
- break;
- case '~':
- check_spaces_left(line, lineno, n);
- break;
- case '!':
- /* != */
- if (line[n + 1] == '=')
- {
- check_spaces_leftright(line, lineno, n, n + 1);
- n++;
- }
- /* !! */
- else if (line[n + 1] == '!')
- {
- check_spaces_left(line, lineno, n);
- n++;
- }
- else
- {
- check_spaces_left(line, lineno, n);
- }
- break;
- default:
- break;
- }
- }
- }
- /* Loop terminates when NUL or newline character found */
- if (line[n] == '\n' || line[n] == '\0')
- {
- /* If the parse terminated on the NULL, then back up to the last
- * character (which should be the newline).
- */
- int m = n;
- if (line[m] == '\0' && m > 0)
- {
- m--;
- }
- /* Check for space at the end of the line. Except for carriage
- * returns which we have already reported (one time) above.
- */
- if (m > 1 && isspace((int)line[m - 1]) &&
- line[m - 1] != '\n' && line[m - 1] != '\r')
- {
- ERROR("Dangling whitespace at the end of line", lineno, m);
- }
- /* The line width is determined by the location of the final
- * asterisk in block comments. The closing line of the block
- * comment will exceed that by one one character, the '/'
- * following the final asterisk.
- */
- else if (m > g_maxline)
- {
- bool bslash;
- int a;
- for (bslash = false, a = m;
- a > 2 && strchr("\n\r/", line[a]) != NULL;
- a--)
- {
- if (line[a] == '/')
- {
- bslash = true;
- }
- }
- if (bslash && line[a] == '*')
- {
- m = a + 1;
- }
- }
- /* Check for long lines
- *
- * REVISIT: Long line checks suppressed on right hand comments
- * for now. This just prevents a large number of difficult-to-
- * fix complaints that we would have otherwise.
- */
- if (m > g_maxline && !rhcomment)
- {
- ERROR("Long line found", lineno, m);
- }
- }
- /* STEP 4: Check alignment */
- /* Within a comment block, we need only check on the alignment of the
- * comment.
- */
- if ((ncomment > 0 || prevncomment > 0) && !bstring)
- {
- /* Nothing should begin in comment zero */
- if (indent == 0 && line[0] != '/' && !bexternc)
- {
- /* NOTE: if this line contains a comment to the right of the
- * code, then ncomment will be misleading because it was
- * already incremented above.
- */
- if (ncomment > 1 || rhcomment == 0)
- {
- ERROR("No indentation line", lineno, indent);
- }
- }
- else if (indent == 1 && line[0] == ' ' && line[1] == '*')
- {
- /* Good indentation */
- }
- else if (indent > 0 && line[indent] == '\n')
- {
- ERROR("Whitespace on blank line", lineno, indent);
- }
- else if (indent > 0 && indent < 2)
- {
- if (bnest > 0)
- {
- ERROR("Insufficient indentation", lineno, indent);
- }
- else
- {
- ERROR("Expected indentation line", lineno, indent);
- }
- }
- else if (indent > 0 && !bswitch)
- {
- if (line[indent] == '/')
- {
- /* Comments should like at offsets 2, 6, 10, ...
- * This rule is not followed, however, if the comments are
- * aligned to the right of the code.
- */
- if ((indent & 3) != 2 && rhcomment == 0)
- {
- ERROR("Bad comment alignment", lineno, indent);
- }
- /* REVISIT: This screws up in cases where there is C code,
- * followed by a comment that continues on the next line.
- */
- else if (line[indent + 1] != '*')
- {
- ERROR("Missing asterisk in comment", lineno, indent);
- }
- }
- else if (line[indent] == '*')
- {
- /* REVISIT: Generates false alarms on comments at the end of
- * the line if there is nothing preceding (such as the aligned
- * comments with a structure field definition). So disabled
- * for comments before beginning of function definitions.
- *
- * Suppress this error if this is a comment to the right of
- * code.
- * Those may be unaligned.
- */
- if ((indent & 3) != 3 && bfunctions && dnest == 0 &&
- rhcomment == 0)
- {
- ERROR("Bad comment block alignment", lineno, indent);
- }
- if (line[indent + 1] != ' ' &&
- line[indent + 1] != '*' &&
- line[indent + 1] != '\n' &&
- line[indent + 1] != '/')
- {
- ERROR("Invalid character after asterisk "
- "in comment block", lineno, indent);
- }
- }
- /* If this is not the line containing the comment start, then this
- * line should begin with '*'
- */
- else if (prevncomment > 0)
- {
- ERROR("Missing asterisk in comment block", lineno, indent);
- }
- }
- }
- /* Check for various alignment outside of the comment block */
- else if ((ncomment == 0 && prevncomment == 0) && !bstring)
- {
- if (indent == 0 && strchr("\n#{}", line[0]) == NULL)
- {
- /* Ignore if we are at global scope */
- if (prevbnest > 0)
- {
- bool blabel = false;
- if (isalpha((int)line[indent]))
- {
- for (i = indent + 1; isalnum((int)line[i]) ||
- line[i] == '_'; i++);
- blabel = (line[i] == ':');
- }
- if (!blabel && !bexternc)
- {
- ERROR("No indentation line", lineno, indent);
- }
- }
- }
- else if (indent == 1 && line[0] == ' ' && line[1] == '*')
- {
- /* Good indentation */
- }
- else if (indent > 0 && line[indent] == '\n')
- {
- ERROR("Whitespace on blank line", lineno, indent);
- }
- else if (indent > 0 && indent < 2)
- {
- ERROR("Insufficient indentation line", lineno, indent);
- }
- else if (line[indent] == '{')
- {
- /* Check for left brace in first column, but preceded by a
- * blank line. Should never happen (but could happen with
- * internal compound statements).
- */
- if (indent == 0 && lineno == blank_lineno + 1)
- {
- ERROR("Blank line before opening left brace", lineno, indent);
- }
- /* REVISIT: Possible false alarms in compound statements
- * without a preceding conditional. That usage often violates
- * the coding standard.
- */
- else if (!bfunctions && (indent & 1) != 0)
- {
- ERROR("Bad left brace alignment", lineno, indent);
- }
- else if ((indent & 3) != 0 && !bswitch && dnest == 0)
- {
- ERROR("Bad left brace alignment", lineno, indent);
- }
- }
- else if (line[indent] == '}')
- {
- /* REVISIT: Possible false alarms in compound statements
- * without a preceding conditional. That usage often violates
- * the coding standard.
- */
- if (!bfunctions && (indent & 1) != 0)
- {
- ERROR("Bad left brace alignment", lineno, indent);
- }
- else if ((indent & 3) != 0 && !bswitch && prevdnest == 0)
- {
- ERROR("Bad right brace alignment", lineno, indent);
- }
- }
- else if (indent > 0)
- {
- /* REVISIT: Generates false alarms when a statement continues on
- * the next line. The bstatm check limits to lines beginning
- * with C keywords.
- * REVISIT: The bstatm check will not detect statements that
- * do not begin with a C keyword (such as assignment statements).
- * REVISIT: Generates false alarms on comments at the end of
- * the line if there is nothing preceding (such as the aligned
- * comments with a structure field definition). So disabled for
- * comments before beginning of function definitions.
- */
- if ((bstatm || /* Begins with C keyword */
- (line[indent] == '/' && bfunctions)) && /* Comment in functions */
- !bswitch && /* Not in a switch */
- dnest == 0) /* Not a data definition */
- {
- if ((indent & 3) != 2)
- {
- ERROR("Bad alignment", lineno, indent);
- }
- }
- /* Crazy cases. There should be no small odd alignments
- * outside of comment/string. Odd alignments are possible
- * on continued lines, but not if they are small.
- */
- else if (indent == 1 || indent == 3)
- {
- ERROR("Small odd alignment", lineno, indent);
- }
- }
- }
- }
- if (!bfunctions && g_file_type == C_SOURCE)
- {
- ERROR("\"Private/Public Functions\" not found!"
- " File will not be checked", lineno, 1);
- }
- if (ncomment > 0 || bstring)
- {
- ERROR("Comment or string found at end of file", lineno, 1);
- }
- fclose(instream);
- if (g_verbose == 1)
- {
- fprintf(stderr, "%s: %s nxstyle check\n", g_file_name,
- g_status == 0 ? "PASSED" : "FAILED");
- }
- return g_status;
- }
|