Annotation of researchv10no/cmd/snocone/snocone.sc, revision 1.1

1.1     ! root        1:        DATA("b(op,l,r)")
        !             2:        DATA("u(op,r)")
        !             3:        DATA("i_fcall(name,head,tail)")
        !             4:        DATA("fcall(name,args,l,r)")
        !             5:        DATA("argexp(exp,next)")
        !             6: 
        !             7:        stack = TABLE()
        !             8:        bconv = TABLE(30)
        !             9:        deflist = TABLE(50)
        !            10:        inctab = TABLE()
        !            11:        stno_tab = TABLE(100)
        !            12: 
        !            13:        # The "binfo" structure contains the information needed to
        !            14:        # map Snocone binary operators into SNOBOL4 binary operators.
        !            15:        # The significance of the fields is as follows:
        !            16:        #
        !            17:        #       out     The corresponding SNOBOL4 operator
        !            18:        #       lp      The operator priority when it's on the left
        !            19:        #               side of a precedence comparison
        !            20:        #       rp      The operator priority when it's on the right
        !            21:        #               side of a precedence comparison.  lp is always
        !            22:        #               equal to rp or rp-1; if equal, the operator is
        !            23:        #               left-associative, otherwise right-associative.
        !            24:        #       slp     Like lp, but for the SNOBOL4 operator
        !            25:        #       srp     Like rp, but for the SNOBOL4 operator
        !            26:        #       fn      Non-null if this operator translates into a
        !            27:        #               call to a built-in function instead of an operator.
        !            28:        DATA("binfo(out,lp,rp,slp,srp,fn)")
        !            29: 
        !            30:        # Paren isn't really an operator, but precedence comparisons
        !            31:        # work out more easily if bconv has an entry for them.
        !            32:        bconv['('] = par_binfo = binfo('',0)
        !            33: 
        !            34:        bconv['='] = binfo('=',1,2,0,1)
        !            35:        bconv['?'] = binfo('?',2,2,1,1)
        !            36:        bconv['|'] = binfo('|',3,3,2,2)
        !            37:        bconv['||'] = or_binfo = binfo('',4,4,0,0,1)
        !            38:        bconv['&&'] = cat_binfo = binfo(' ',5,5,4,4)
        !            39:        bconv['>'] = binfo('GT',6,6,0,0,1)
        !            40:        bconv['<'] = binfo('LT',6,6,0,0,1)
        !            41:        bconv['>='] = binfo('GE',6,6,0,0,1)
        !            42:        bconv['<='] = binfo('LE',6,6,0,0,1)
        !            43:        bconv['=='] = binfo('EQ',6,6,0,0,1)
        !            44:        bconv['!='] = binfo('NE',6,6,0,0,1)
        !            45:        bconv['::'] = binfo('IDENT',6,6,0,0,1)
        !            46:        bconv[':!:'] = binfo('DIFFER',6,6,0,0,1)
        !            47:        bconv[':>:'] = binfo('LGT',6,6,0,0,1)
        !            48:        bconv[':<:'] = binfo('LLT',6,6,0,0,1)
        !            49:        bconv[':>=:'] = binfo('LGE',6,6,0,0,1)
        !            50:        bconv[':<=:'] = binfo('LLE',6,6,0,0,1)
        !            51:        bconv[':==:'] = binfo('LEQ',6,6,0,0,1)
        !            52:        bconv[':!=:'] = binfo('LNE',6,6,0,0,1)
        !            53:        bconv['+'] = binfo('+',7,7,5,5)
        !            54:        bconv['-'] = binfo('-',7,7,5,5)
        !            55:        bconv['/'] = binfo('/',8,8,7,7)
        !            56:        bconv['*'] = binfo('*',8,8,8,8)
        !            57:        bconv['%'] = binfo('REMDR',8,8,0,0,1)
        !            58:        bconv['^'] = binfo('**',9,10,10,11)
        !            59:        bconv['.'] = binfo('.',10,10,11,11)
        !            60:        bconv['$'] = binfo('$',10,10,11,11)
        !            61: 
        !            62:        ht = char(9)
        !            63:        optblank = nspan(" " && ht)
        !            64:        blank = SPAN(" " && ht)
        !            65:        digits = "0123456789"
        !            66:        letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_"
        !            67: 
        !            68:        integer = SPAN(digits)
        !            69:        exponent = ANY("eEdD") && (ANY("+-") | "") && integer
        !            70:        real = integer && "." && (integer | "") && (exponent | "") |
        !            71:                integer && exponent | "." && integer && (exponent | "")
        !            72:        number = real | integer
        !            73: 
        !            74:        string = ANY("'" && '"') $ squote && BREAK(*squote) && LEN(1)
        !            75: 
        !            76:        constant = number | string
        !            77:        identifier = ANY(letters) && nspan(letters && digits)
        !            78:        unaryop = ANY("+-*&@~?.$")
        !            79:        binaryop = "==" | "!=" | "<=" | ">=" | "&&" | "||" | ":==:" |
        !            80:                ":!=:" | ":>:" | ":<:" | ":>=" | ":<=:" | "::" | ":!:" | 
        !            81:                ANY("+-*/<>=^.$?|%")
        !            82: 
        !            83:        fcall = identifier . *mkfcall() && optblank &&
        !            84:                (("(" && list(*exp . *invoke(.mkarg), optblank && ",") &&
        !            85:                optblank && ")" . *invoke(.endfc)) |
        !            86:                ("[" && list(*exp . *invoke(.mkarg), optblank && ",") &&
        !            87:                optblank && "]" . *invoke(.endfc) . *invoke(.mkarray)))
        !            88: 
        !            89:        term = optblank && (constant . *push() . *dotck() |
        !            90:                identifier . *push() | "(" && *exp && optblank && ")" | fcall)
        !            91:        operand = term | optblank && unaryop . *push() &&
        !            92:                *operand . *invoke(.unop)
        !            93:        exp = "" . *begexp() && *operand &&
        !            94:                ARBNO(optblank && binaryop . *push() . *invoke(.mkbinfo) &&
        !            95:                *operand . *invoke(.binop)) && "" . *endexp()
        !            96: 
        !            97:        label = optblank && identifier . lab . *emitlab(lab) && optblank && ":"
        !            98: 
        !            99:        clausend = ANY("{}") . del | RPOS(0)
        !           100: 
        !           101:        clause = FENCE && ARBNO(label) && optblank &&
        !           102:                ("if" . cl_type && optblank && "(" && *exp && optblank && ")" |
        !           103:                "while" . cl_type && optblank && "(" && *exp && optblank && ")" |
        !           104:                (kw("return") | kw("freturn") | kw("nreturn")) . cl_type &&
        !           105:                        optblank && ("" . *push() | *exp) &&
        !           106:                        optblank && clausend |
        !           107:                "go" && optblank && "to" && blank &&
        !           108:                        identifier . dest . *invoke(.gocl) |
        !           109:                ("{" | "}") . cl_type |
        !           110:                ("do" | kw("else")) . cl_type && (SPAN(" " && ht) | RPOS(0)) |
        !           111:                "procedure" . cl_type && blank && identifier . fname |
        !           112:                "struct" . cl_type && blank && identifier . stname |
        !           113:                "for" . cl_type && optblank &&
        !           114:                        "(" && *exp && optblank && "," && *exp && optblank &&
        !           115:                        "," && *exp && optblank && ")" |
        !           116:                RPOS(0) . cl_type && *invoke(.emiteos) |
        !           117:                *exp && optblank && clausend . *invoke(.expcl))
        !           118: 
        !           119:        gl_files = TABLE()
        !           120:        gl_lines = TABLE()
        !           121:        gl_index = -1
        !           122: 
        !           123:        emit_stno = 0
        !           124: 
        !           125:        &STLIMIT = 1000000000
        !           126: #
        !           127: #      save the current state -- we really begin execution here.
        !           128:        EXIT(3)
        !           129: #
        !           130: #      Establish a starting point for input files
        !           131:        gl_arg = HOST(3) - 1
        !           132:        if (~HOST (2, HOST(3))) {
        !           133:                OUTPUT = "snocone: nothing to compile"
        !           134:                go to END
        !           135:        }
        !           136: 
        !           137:        if (~gl_nextfile()) {
        !           138:                go to END
        !           139:        }
        !           140: #
        !           141: #      establish the "object" file
        !           142:        outfile = "a.out"
        !           143:        &ERRLIMIT = &ERRLIMIT + 1
        !           144:        savexit = SETEXIT()
        !           145:        if (~OUTPUT(.outf,-1,outfile)) {
        !           146:                OUTPUT = "cannot write " && outfile
        !           147:                go to END
        !           148:        }
        !           149:        &ERRLIMIT = &ERRLIMIT - 1
        !           150:        SETEXIT (savexit)
        !           151: 
        !           152:        outf = "#!/usr/bin/spitbol -s16k"
        !           153:        outf = "-in4096"
        !           154: #
        !           155: #      Permanent prologue
        !           156:        emitlab("MAIN.")
        !           157: #
        !           158: #      The main loop.  We expect to read a series of statements.
        !           159:        while (nclause (1)) {
        !           160:                if (IDENT (cl_type, "procedure"))
        !           161:                        funct()
        !           162:                else if (IDENT (cl_type, "struct"))
        !           163:                        dostruct()
        !           164:                else
        !           165:                        dostmt()
        !           166:        }
        !           167: 
        !           168: 
        !           169: #      Epilogue
        !           170: EXIT:
        !           171:        emitg("END")
        !           172:        emitlab("START.")
        !           173:        emit("CODE('START.')")
        !           174:        for (i = 1, i <= deflist[0], i = i + 1) {
        !           175:                emiteos()
        !           176:                emit(deflist[i])
        !           177:        }
        !           178: 
        !           179:        # put out code to trap run-time errors
        !           180:        emiteos()
        !           181:        emit("&ERRLIMIT = 1")
        !           182:        emiteos()
        !           183:        emit("SETEXIT(.err.exit)")
        !           184: 
        !           185:        # put out code to assign the statement map
        !           186:        emiteos()
        !           187:        emit ("err.map = '")
        !           188:        while (bst_stab ? LEN(50) . bst_chunk = "") {
        !           189:                emit (bst_chunk && "'")
        !           190:                emiteos()
        !           191:                emitlab("+")
        !           192:                emit("'")
        !           193:        }
        !           194:        emit (bst_stab && "'")
        !           195: 
        !           196:        emitg("MAIN.")
        !           197:        emiteos()
        !           198: 
        !           199: #      Epilogue
        !           200:        INPUT(.inf,-2,'/usr/lib/snocone/epilogue')
        !           201:        while (line = inf)
        !           202:                outf = line
        !           203:        ENDFILE(-2)
        !           204: 
        !           205:        ENDFILE(-1)
        !           206:        HOST (1, "chmod +x " && outfile)
        !           207: 
        !           208: 
        !           209: 
        !           210: #                      subroutines
        !           211: 
        !           212: 
        !           213: 
        !           214: 
        !           215: #      like span, but the pattern returned
        !           216: #      can also match the null string
        !           217: procedure nspan (str) {
        !           218:        return SPAN (str) | ""
        !           219: }
        !           220: 
        !           221: #      a pattern that matches a list of zero or more
        !           222: #      "item"s separated by "delim"s
        !           223: procedure list (item, delim) {
        !           224:        return item && ARBNO (delim && item) | ""
        !           225: }
        !           226: 
        !           227: #      a pattern that matches the keyword given by the
        !           228: #      argument, insisting that it be followed by a non-letter.
        !           229: procedure kw (s) {
        !           230:        return SPAN(letters) $ dummy &&
        !           231:                CONVERT("ident(dummy,'" && s && "')", "EXPRESSION")
        !           232: }
        !           233: 
        !           234: #      return the name of the (new) top stack element
        !           235: procedure push() {
        !           236:        stackptr = stackptr + 1
        !           237:        nreturn  .stack[stackptr]
        !           238: }
        !           239: 
        !           240: #      return the value of the (old) top stack element
        !           241: procedure pop() {
        !           242:        pop = stack[stackptr]
        !           243:        stack[stackptr] = ""
        !           244:        stackptr = stackptr - 1
        !           245: }
        !           246: 
        !           247: #      return the name of the stack element n away from the top
        !           248: procedure peek (n) {
        !           249:        if (n >= stackptr)
        !           250:                go to err
        !           251:        nreturn .stack[stackptr - n]
        !           252: }
        !           253: 
        !           254: #      top()
        !           255: #      return the name of the top stack element
        !           256: procedure top() {
        !           257:        nreturn .stack[stackptr]
        !           258: }
        !           259: 
        !           260: #      isbin(x)
        !           261: #      is x a structure describing a binary operator?
        !           262: #      things like == and ||, which syntactically look
        !           263: #      more like functions than operators in their snobol form,
        !           264: #      are considered not to be operators.
        !           265: procedure isbin (x) {
        !           266:        if (DIFFER (DATATYPE (x), 'B') || DIFFER (fn (op (x))))
        !           267:                freturn
        !           268: }
        !           269: 
        !           270: #      isneg(x)
        !           271: #      is x a structure describing a unary negation operator?
        !           272: procedure isneg (x) {
        !           273:        if (DIFFER (DATATYPE (x), 'U') || DIFFER (op (x), '~'))
        !           274:                freturn
        !           275: }
        !           276: 
        !           277: #
        !           278: #      print an expression in snobol form
        !           279: procedure dprint (x) op, l, r, d, i, del {
        !           280:        d = DATATYPE(x)
        !           281:        if (IDENT (d, 'STRING')) {
        !           282:                emit (x)
        !           283:                return
        !           284:        }
        !           285: 
        !           286:        if (IDENT (d, 'U')) {
        !           287:                # unary operator
        !           288:                emit (op (x))
        !           289:                if (isbin(r(x)))
        !           290:                        emit('(')
        !           291:                dprint(r(x))
        !           292:                if (isbin(r(x)))
        !           293:                        emit(')')
        !           294:                return
        !           295:        }
        !           296: 
        !           297: 
        !           298:        if (IDENT (d, 'FCALL')) {
        !           299:                # function call or array reference
        !           300:                emit (name (x))
        !           301:                emit (l (x))
        !           302:                r = args (x)
        !           303:                while (DIFFER (r)) {
        !           304:                        emit (del)
        !           305:                        dprint (exp (r))
        !           306:                        del = ','
        !           307:                        r = next (r)
        !           308:                }
        !           309:                emit (r (x))
        !           310:                return
        !           311:        }
        !           312: 
        !           313:        if (IDENT (d, 'B')) {
        !           314:                # binary operator
        !           315:                op = op (x)
        !           316:                if (IDENT (op, or_binfo)) {
        !           317:                        emit ('(')
        !           318:                        bprint (x)
        !           319:                        emit (')')
        !           320:                        return
        !           321:                }
        !           322:                l = isbin(l(x)) && slp(op(l(x))) < srp(op) && 1 || ""
        !           323:                r = isbin(r(x)) && slp(op) > srp(op(r(x))) && 1 || ""
        !           324: 
        !           325:                # check for [f](a,b)
        !           326:                if (DIFFER (fn (op))) {
        !           327:                        emit(out(op))
        !           328:                        emit('(')
        !           329:                        dprint(l(x))
        !           330:                        emit(',')
        !           331:                        dprint(r(x))
        !           332:                        emit(')')
        !           333:                        return
        !           334:                }
        !           335: 
        !           336:                # ordinary binary operator
        !           337:                if (DIFFER (l))
        !           338:                        emit ('(')
        !           339:                dprint(l(x))
        !           340:                if (DIFFER (l))
        !           341:                        emit (')')
        !           342:                emitb(out(op))
        !           343:                if (DIFFER(r))
        !           344:                        emit('(')
        !           345:                dprint(r(x))
        !           346:                if (DIFFER(r))
        !           347:                        emit(')')
        !           348:                return
        !           349:        }
        !           350: 
        !           351:        # unknown datatype -- this "shouldn't happen"
        !           352:        i = 1
        !           353:        emit(d)
        !           354:        emit ('(')
        !           355:        while (dprint (APPLY (FIELD (d, i), x))) {
        !           356:                i = i + 1
        !           357:                emit (',')
        !           358:        }
        !           359:        emit (')')
        !           360: }
        !           361: 
        !           362: #      bprint(x)
        !           363: #      subroutine of dprint -- used to handle printing of
        !           364: #      things of the form (a,b), which are inherently
        !           365: #      associative and can therefore be grouped as follows
        !           366: #      ((a,b),c) <=>  (a,(b,c)) <=>  (a,b,c)
        !           367: procedure bprint (x) {
        !           368:        if (DIFFER (DATATYPE(x), 'B') || DIFFER (op(x), or_binfo)) {
        !           369:                dprint (x)
        !           370:                return
        !           371:        }
        !           372:        bprint(l(x))
        !           373:        emit(',')
        !           374:        bprint(r(x))
        !           375: }
        !           376: 
        !           377: #      sprint(x)
        !           378: #      like dprint, but print in a form appropriate for
        !           379: #      an entire statement.  This procedure exists
        !           380: #      because if the top level operator is a concatenation,
        !           381: #      it is necessary to enclose the whole thing in parentheses.
        !           382: #      Otherwise it would be mistaken for a pattern match.
        !           383: procedure sprint (x) {
        !           384:        if (IDENT(DATATYPE(x),'B') && IDENT(op(x),cat_binfo))
        !           385:                emit('(')
        !           386:        dprint(x)
        !           387:        if (IDENT(DATATYPE(x),'B') && IDENT(op(x),cat_binfo))
        !           388:                emit(')')
        !           389:        emiteob()
        !           390: }
        !           391: 
        !           392: #      invoke(f)
        !           393: #      call an argument-free function in a context where
        !           394: #      a name is required, such as    arb . *invoke(.foo)
        !           395: procedure invoke (f) {
        !           396:        APPLY (f)
        !           397:        nreturn .dummy
        !           398: }
        !           399: 
        !           400: #      a unary operator has been detected during parsing
        !           401: procedure unop() r, op {
        !           402:        r = pop()
        !           403:        op = pop()
        !           404:        push() = u(op,r)
        !           405: }
        !           406: 
        !           407: #      mkfcall()
        !           408: #      Parsing has detected the beginning of a function call
        !           409: procedure mkfcall() {
        !           410:        push() = i_fcall()
        !           411:        nreturn .name(top())
        !           412: }
        !           413: 
        !           414: #      parsing has detected an argument to a function
        !           415: procedure mkarg() x, f {
        !           416:        x = argexp(pop(),"")
        !           417:        f = top()
        !           418:        if (DIFFER(tail(f)))
        !           419:                next(tail(f)) = x
        !           420:        tail(f) = x
        !           421:        head(f) = IDENT(head(f)) && x
        !           422: }
        !           423: 
        !           424: #      parsing has detected the end of a function call
        !           425: procedure endfc() f {
        !           426:        f = pop()
        !           427:        push() = fcall(name(f),head(f),'(',')')
        !           428: }
        !           429: 
        !           430: #      the fcall at the head of the stack is really an array
        !           431: procedure mkarray() t {
        !           432:        t = top()
        !           433:        l(t) = '<'
        !           434:        r(t) = '>'
        !           435: }
        !           436: 
        !           437: #      the beginning of an expression has been detected
        !           438: procedure begexp() {
        !           439:        push() = bconv['(']
        !           440:        nreturn .dummy
        !           441: }
        !           442: 
        !           443: #      a binary operator has been detected.  We handle
        !           444: #      precedence here rather than in the grammar
        !           445: #      because it is less work.
        !           446: procedure binop() l, r, op, newr, newop {
        !           447:        while (lp(peek(3)) >= rp(peek(1))) {
        !           448:                newr = pop()
        !           449:                newop = pop()
        !           450:                r = pop()
        !           451:                op = pop()
        !           452:                l = pop()
        !           453:                push() = b(op,l,r)
        !           454:                push() = newop
        !           455:                push() = newr
        !           456:        }
        !           457: }
        !           458: 
        !           459: #      the end of an expression has been detected
        !           460: procedure endexp() l, r, op {
        !           461:        while (DIFFER (peek (1), par_binfo)) {
        !           462:                r = pop()
        !           463:                op = pop()
        !           464:                l = pop()
        !           465:                push() = b(op,l,r)
        !           466:        }
        !           467:        r = pop()
        !           468:        pop()
        !           469:        push() = r
        !           470:        nreturn .dummy
        !           471: }
        !           472: 
        !           473: #      locate the binfo structure that describes the
        !           474: #      binary operator whose input character representation
        !           475: #      has been placed on the top of the stack.
        !           476: procedure mkbinfo() op {
        !           477:        op = bconv[pop()]
        !           478:        if (IDENT(op))
        !           479:                go to err
        !           480:        push() = op
        !           481: }
        !           482: 
        !           483: #      dotck()
        !           484: #      if necessary, append a leading zero to a floating-point
        !           485: #      constant that begins with a decimal point.  The idea
        !           486: #      that .5 is syntactically correct but semantically illegal
        !           487: #      is just too scary to leave in.
        !           488: procedure dotck() {
        !           489:        top() ? FENCE && '.' = '0.'
        !           490:        nreturn .dummy
        !           491: }
        !           492: 
        !           493: #      write label l to the output
        !           494: procedure emitlab (l) {
        !           495:        if (DIFFER(l)) {
        !           496:                emiteos()
        !           497:                st_lab = l
        !           498:        }
        !           499:        nreturn .dummy
        !           500: }
        !           501: 
        !           502: #      put string s in the output
        !           503: procedure emit (s) {
        !           504:        if (DIFFER(emit_eob))
        !           505:                emiteos()
        !           506:        st_body = st_body && s
        !           507: }
        !           508: 
        !           509: #      we are done with the body of the generated statement
        !           510: procedure emiteob() {
        !           511:        if (IDENT (emit_eob)) {
        !           512:                buildstab (emit_stno, gi_file, gi_line)
        !           513:                emit_eob = 1
        !           514:        }
        !           515: }
        !           516: 
        !           517: #      write success branch l
        !           518: procedure emits (l) {
        !           519:        emiteob()
        !           520:        st_s = l
        !           521: }
        !           522: 
        !           523: #      emitf(l)
        !           524: #      write failure branch l
        !           525: procedure emitf (l) {
        !           526:        emiteob()
        !           527:        st_f = l
        !           528: }
        !           529: 
        !           530: #      write unconditional branch l
        !           531: procedure emitg (l) {
        !           532:        emiteob()
        !           533:        st_s = IDENT(st_s) && l
        !           534:        st_f = IDENT(st_f) && l
        !           535: }
        !           536: 
        !           537: #      write s surrounded by blanks
        !           538: procedure emitb (s) {
        !           539:        emit(' ')
        !           540:        if (DIFFER (s, ' ')) {
        !           541:                emit (s)
        !           542:                emit(' ')
        !           543:        }
        !           544: }
        !           545: 
        !           546: #      emiteos()out,goto
        !           547: #      we are done with the entire statement
        !           548: procedure emiteos() out, goto, s, del {
        !           549:        emit_eob = ""
        !           550:        if (DIFFER(st_lab) || DIFFER(st_body) || DIFFER(st_s) || DIFFER(st_f)) {
        !           551:                emit_stno = emit_stno + 1
        !           552:                out = st_lab && " " && st_body
        !           553:                if (DIFFER (st_s) || DIFFER (st_f)) {
        !           554:                        goto = " :"
        !           555:                        if (IDENT (st_s, st_f))
        !           556:                                goto = goto && "(" && st_s && ")"
        !           557:                        else {
        !           558:                                if (DIFFER (st_s))
        !           559:                                        goto = goto && "S(" && st_s && ")"
        !           560:                                if (DIFFER (st_f))
        !           561:                                        goto = goto && "F(" && st_f && ")"
        !           562:                        }
        !           563:                }
        !           564:                out = out && goto
        !           565:                while (SIZE(out) >= 70 && (out ? FENCE &&
        !           566:                                (ARBNO(BREAK(" '" && '"') &&
        !           567:                                (" " | ANY("'" && '"') $ del &&
        !           568:                                BREAK(*del) && LEN(1))) $ s &&
        !           569:                                *(SIZE(s) > 50)) . outf = "+"))
        !           570:                        {}
        !           571:                outf = out
        !           572:                st_lab = st_body = st_s = st_f = ""
        !           573:        }
        !           574: }
        !           575: 
        !           576: # attempt to read an input line, taking #include into account
        !           577: procedure getline() x, file, del, dir {
        !           578:        do {
        !           579:                # Try to read a line from the current file
        !           580:                while (x = gl_in) {
        !           581: 
        !           582:                        # We have a line: count it
        !           583:                        gl_line = gl_line + 1
        !           584: 
        !           585:                        # If it's not an include statement, we're done.
        !           586:                        if (~(x ? FENCE && "#" && *optblank && "include" &&
        !           587:                            *optblank && ANY('"<{' && "'") $ del &&
        !           588:                            BREAK(*REPLACE(del,'<{','>}')) . file &&
        !           589:                            LEN (1) && *optblank && RPOS(0)))
        !           590:                                return x
        !           591: 
        !           592:                        # If the name is enclosed in quotes and
        !           593:                        # relative, then it is relative to the
        !           594:                        # directory containing the currently included
        !           595:                        # file, if any.  If it is enclosed in brackets,
        !           596:                        # it is relative to a canonical directory.
        !           597:                        if ("'" && '"' ? del) {
        !           598:                                if (SUBSTR (file, 1, 1) :!=: '/') {
        !           599:                                        if ((gl_file && '/') ? FENCE &&
        !           600:                                            (BREAKX('/') && LEN(1)) . dir &&
        !           601:                                            BREAK('/') && LEN(1) && RPOS(0))
        !           602:                                                file = dir && file
        !           603:                                }
        !           604:                        } else
        !           605:                                file = "/usr/lib/snocone/" && file
        !           606: 
        !           607:                        # If the name was enclosed by single quotes
        !           608:                        # or set brackets, ensure the particular file
        !           609:                        # was included only once.  Right now, we're pretty
        !           610:                        # literal-minded about when two files are really
        !           611:                        # the same:  'x' and './x' are different, for instance.
        !           612:                        if (('"<' ? del) || IDENT (inctab[file])) {
        !           613:                                inctab[file] = 1
        !           614:                                gl_open (file)
        !           615:                        }
        !           616:                }
        !           617: 
        !           618:                # We've reached the end of this file.
        !           619:                gl_close()
        !           620:        } while (gl_index >= 0 || gl_nextfile());
        !           621: 
        !           622:        freturn
        !           623: }
        !           624: 
        !           625: procedure gl_nextfile() {
        !           626:        gl_arg = gl_arg + 1
        !           627:        if (~gl_open (HOST (2, gl_arg)))
        !           628:                freturn
        !           629: }
        !           630: 
        !           631: procedure gl_close() {
        !           632:        ENDFILE (gl_index)
        !           633:        gl_index = gl_index - 1
        !           634:        gl_file = gl_files[gl_index]
        !           635:        gl_line = gl_lines[gl_index]
        !           636:        if (gl_index >= 0)
        !           637:                INPUT(.gl_in, gl_index)
        !           638:        gl_files[gl_index] = gl_lines[gl_index] = ""
        !           639: }
        !           640: 
        !           641: procedure gl_open (file) t {
        !           642:        gl_files[gl_index] = gl_file
        !           643:        gl_lines[gl_index] = gl_line
        !           644:        gl_index = gl_index + 1
        !           645:        gl_line = 0
        !           646:        gl_file = file
        !           647:        &ERRLIMIT = &ERRLIMIT + 1
        !           648:        t = SETEXIT()
        !           649:        if (INPUT (.gl_in, gl_index, file)) {
        !           650:                SETEXIT(t)
        !           651:                &ERRLIMIT = &ERRLIMIT - 1
        !           652:                return
        !           653:        }
        !           654:        SETEXIT(t)
        !           655:        gl_close()
        !           656:        error ("cannot read " && file)
        !           657:        freturn
        !           658: }
        !           659: 
        !           660: # Attempt to read an input line, return on ultimate failure.
        !           661: # This procedure strips comments and handles continuation lines.
        !           662: procedure getinput (recur) del, line {
        !           663: 
        !           664:        # have we already encountered the last EOF?
        !           665:        if (DIFFER (gi_eof))
        !           666:                freturn
        !           667: 
        !           668:        if (line = line && getline()) {
        !           669: 
        !           670:                # if this is the first line, remember its identity
        !           671:                if (IDENT (recur)) {
        !           672:                        gi_file = gl_file
        !           673:                        gi_line = gl_line
        !           674:                }
        !           675: 
        !           676:                # strip comments
        !           677:                line ?
        !           678:                    FENCE &&
        !           679:                        (ARBNO (BREAK ("'" && '"') &&
        !           680:                            LEN(1) $ del && BREAK (*del) && LEN(1)) &&
        !           681:                        BREAK ("'" && '"#')) . line && "#"
        !           682:                
        !           683:                # check for continuation
        !           684:                if (line? ANY("@$%^&*(-+=[<>|~,?:") && optblank && RPOS(0))
        !           685:                        line = line && getinput(1)
        !           686: 
        !           687:                return line
        !           688:        }
        !           689: 
        !           690:        # we're out of input - signal final eof
        !           691:        gi_eof = 1
        !           692:        freturn
        !           693: }
        !           694: 
        !           695: #      phrase()
        !           696: #      return the next phrase from the input
        !           697: procedure phrase() del {
        !           698:        if (ph_buf ? FENCE && optblank && RPOS(0)) {
        !           699:                if (ph_buf = phbuf && getinput())
        !           700:                        return phrase()
        !           701:                else
        !           702:                        freturn
        !           703:        }
        !           704: 
        !           705:        if (ph_buf ? FENCE &&
        !           706:            (ARBNO(BREAK('"' && "'") && LEN(1) $ del && BREAK(*del) &&
        !           707:            LEN(1)) && BREAK('"' && "';")) . phrase && ';' = '')
        !           708:                return
        !           709: 
        !           710:        phrase = ph_buf
        !           711:        ph_buf = ''
        !           712: }
        !           713: 
        !           714: #      return a new label
        !           715: procedure newlab() {
        !           716:        nl_count = nl_count + 1
        !           717:        return "L." && nl_count
        !           718: }
        !           719: 
        !           720: #      return a new label and place it on the current statement.
        !           721: #      If the current statement already has a label, use that.
        !           722: procedure marklab() {
        !           723:        if (DIFFER (st_lab) && IDENT (emit_eob))
        !           724:                return st_lab
        !           725:        marklab = newlab()
        !           726:        emitlab (marklab)
        !           727: }
        !           728: 
        !           729: #      little routines to indicate what type of clause was read
        !           730: 
        !           731: #      expression clause
        !           732: procedure expcl() {
        !           733:        cl_type = "exp"
        !           734: }
        !           735: 
        !           736: #      goto clause
        !           737: procedure gocl() {
        !           738:        cl_type = "goto"
        !           739: }
        !           740: 
        !           741: #      read a new clause and classify it
        !           742: #      if end of input, error unless "okeof" argument is non-null,
        !           743: #      in which case we merely fail
        !           744: #      if rep_clause is set, give us the last clause again
        !           745: procedure nclause (okeof) del {
        !           746: nclause_start:
        !           747:        if (DIFFER (rep_clause)) {
        !           748:                rep_clause = ""
        !           749:                if (IDENT (eof))
        !           750:                        return
        !           751:                else
        !           752:                        freturn
        !           753:        }
        !           754:        if (linebuf ? FENCE && *optblank && RPOS(0)) {
        !           755:                if (linebuf = phrase())
        !           756:                        go to nclause_start
        !           757: 
        !           758:                #       end of input
        !           759:                if (IDENT(okeof)) {
        !           760:                        error ('premature EOF')
        !           761:                        go to EXIT
        !           762:                }
        !           763:                eof = 1
        !           764:                        freturn
        !           765:        }
        !           766: 
        !           767:        #       we really have some input
        !           768:        if (linebuf ? clause = del)
        !           769:                return
        !           770:        error("syntax error")
        !           771:        linebuf = ""
        !           772:        go to nclause_start
        !           773: }
        !           774: 
        !           775: procedure error (msg) prefix {
        !           776:        if (IDENT (gl_file))
        !           777:                prefix = "snocone"
        !           778:        else
        !           779:                prefix = gl_file && "(" && gl_line && ")"
        !           780:        terminal = prefix && ": " && msg
        !           781:        &CODE = 1
        !           782: }
        !           783: 
        !           784: #      handle a statement
        !           785: procedure dostmt() lab, lab2, e1, e2, e3, flip {
        !           786: 
        !           787:        if (IDENT(cl_type,"exp")) {
        !           788:                #       The clause is an expression,
        !           789:                #       so that's the whole statement
        !           790:                sprint(pop())
        !           791:                return
        !           792:        }
        !           793: 
        !           794:        #       It might be a sequence of statements in braces
        !           795:        if (IDENT(cl_type,"{")) {
        !           796:                nclause()
        !           797:                while (DIFFER (cl_type, "}")) {
        !           798:                        dostmt()
        !           799:                        nclause()
        !           800:                }
        !           801:                return
        !           802:        }
        !           803: 
        !           804:        #       It might be a goto statement
        !           805:        if (IDENT (cl_type, "goto")) {
        !           806:                emitg (dest)
        !           807:                return
        !           808:        }
        !           809: 
        !           810:        #       It might be an if statement
        !           811:        if (IDENT(cl_type,"if")) {
        !           812:                e1 = pop()
        !           813: 
        !           814:                # optimize "if (~expr)"
        !           815:                if (isneg (e1)) {
        !           816:                        flip = 1
        !           817:                        e1 = r(e1)
        !           818:                }
        !           819: 
        !           820:                sprint(e1)
        !           821: 
        !           822:                #       Check for if(...)goto
        !           823:                nclause()
        !           824:                if (IDENT(cl_type,"goto")) {
        !           825:                        if (IDENT (flip))
        !           826:                                emits(dest)
        !           827:                        else
        !           828:                                emitf(dest)
        !           829: 
        !           830:                        #       In the case of if (e) goto l; else ...
        !           831:                        #       we can pretend the else wasn't there
        !           832:                        if (~nclause(1) || DIFFER (cl_type, "else")) {
        !           833:                                rep_clause = 1
        !           834:                                emitlab (lab)
        !           835:                                return
        !           836:                        }
        !           837:                        nclause()
        !           838:                        dostmt()
        !           839:                        return
        !           840:                }
        !           841: 
        !           842:                #       Not if...goto, emit conditional jump over
        !           843:                #       the statement which follows.
        !           844:                lab = newlab()
        !           845:                if (IDENT (flip))
        !           846:                        emitf(lab)
        !           847:                else
        !           848:                        emits(lab)
        !           849:                dostmt()
        !           850: 
        !           851:                #       Check for else clause
        !           852:                if (nclause (1) && IDENT (cl_type, "else")) {
        !           853: 
        !           854:                        #       There is indeed an else clause
        !           855:                        lab2 = newlab()
        !           856:                        emitg(lab2)
        !           857:                        emitlab(lab)
        !           858:                        nclause()
        !           859:                        dostmt()
        !           860:                        emitlab(lab2)
        !           861:                        return
        !           862:                }
        !           863: 
        !           864:                #       No else clause; we must look at this clause again later
        !           865:                rep_clause = 1
        !           866:                emitlab(lab)
        !           867:                return
        !           868:        }
        !           869: 
        !           870:        #       Check for a while clause
        !           871:        if (IDENT(cl_type,"while")) {
        !           872:                lab = marklab()
        !           873: 
        !           874:                # optimize "while(~exp)"
        !           875:                e1 = pop()
        !           876:                if (isneg (e1)) {
        !           877:                        flip = 1
        !           878:                        e1 = r(e1)
        !           879:                }
        !           880: 
        !           881:                sprint(e1)
        !           882:                lab2 = newlab()
        !           883:                if (IDENT (flip))
        !           884:                        emitf(lab2)
        !           885:                else
        !           886:                        emits(lab2)
        !           887:                nclause()
        !           888:                dostmt()
        !           889:                emitg(lab)
        !           890:                emitlab(lab2)
        !           891:                return
        !           892:        }
        !           893: 
        !           894:        #       Check for a do clause
        !           895:        if (IDENT(cl_type,"do")) {
        !           896:                lab = marklab()
        !           897:                nclause()
        !           898:                dostmt()
        !           899:                nclause()
        !           900:                if (DIFFER(cl_type,"while")) {
        !           901:                        error ("expected 'while', found " && cl_type)
        !           902:                        rep_clause = 1
        !           903:                        return
        !           904:                }
        !           905:                e1 = pop()
        !           906:                if (isneg (e1)) {
        !           907:                        flip = 1
        !           908:                        e1 = r (e1)
        !           909:                }
        !           910:                sprint(e1)
        !           911:                if (IDENT (flip))
        !           912:                        emits (lab)
        !           913:                else
        !           914:                        emitf (lab)
        !           915:                return
        !           916:        }
        !           917: 
        !           918:        #       Check for a "for" clause
        !           919:        if (IDENT(cl_type,"for")) {
        !           920:                e3 = pop()
        !           921:                e2 = pop()
        !           922:                e1 = pop()
        !           923:                sprint(e1)
        !           924:                emiteob()
        !           925:                lab = marklab()
        !           926:                lab2 = newlab()
        !           927:                if (isneg (e2)) {
        !           928:                        flip = 1
        !           929:                        e2 = r (e2)
        !           930:                }
        !           931:                sprint(e2)
        !           932:                if (IDENT (flip))
        !           933:                        emitf (lab2)
        !           934:                else
        !           935:                        emits (lab2)
        !           936:                nclause()
        !           937:                dostmt()
        !           938:                sprint(e3)
        !           939:                emitg(lab)
        !           940:                emitlab(lab2)
        !           941:                return
        !           942:        }
        !           943: 
        !           944:        #       could be some kind of return statement
        !           945:        if (cl_type ? "return") {
        !           946:                e1 = pop()
        !           947:                if (DIFFER(e1)) {
        !           948:                        if (DIFFER(fname))
        !           949:                                e1 = b(bconv["="],fname,e1)
        !           950:                        sprint(e1)
        !           951:                }
        !           952:                emitg (REPLACE(cl_type,
        !           953:                        "abcdefghijklmnopqrstuvwxyz",
        !           954:                        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"))
        !           955:                return
        !           956:        }
        !           957: 
        !           958:        #       could even be a null statement
        !           959:        if (IDENT(cl_type))
        !           960:                return
        !           961: 
        !           962:        error("bad " && cl_type && " clause, ignored")
        !           963: }
        !           964: 
        !           965: #      We have seen "struct" -- parse the 'declaration'
        !           966: procedure dostruct() args {
        !           967:        if (expect ('{')) {
        !           968:                args = getlist ('}')
        !           969:                deflist[deflist[0] = deflist[0] + 1] =
        !           970:                        "DATA('" && stname && "(" && args && ")')"
        !           971:        } else
        !           972:                error ("bad structure definition")
        !           973:        expect ('}')
        !           974: }
        !           975: 
        !           976: #      We have seen "procedure" -- we must now parse the header
        !           977: procedure funct() args, locals, flabel {
        !           978:        if (expect('(')) {
        !           979:                if (~(args = getlist(')')))
        !           980:                        go to fu_error
        !           981:                expect(')')
        !           982:                if (~(locals = getlist('{')))
        !           983:                        go to fu_error
        !           984:        }
        !           985: 
        !           986:        deflist[deflist[0] = deflist[0] + 1] =
        !           987:                "DEFINE('" && fname && '(' && args && ')' && locals && "')"
        !           988: 
        !           989:        #       if we just emitted the end of a previous procedure,
        !           990:        #       we can jump around this one in one go
        !           991:        if (IDENT (emit_eob) && st_lab ? ".END") {
        !           992:                flabel = st_lab
        !           993:                st_lab = ""
        !           994:                emitlab(fname)
        !           995:                nclause()
        !           996:                dostmt()
        !           997:                emitg("RETURN")
        !           998:                emitlab(flabel)
        !           999:                return
        !          1000:        }
        !          1001: 
        !          1002:        emitg(fname && '.END')
        !          1003:        emitlab(fname)
        !          1004:        nclause()
        !          1005:        dostmt()
        !          1006:        emitg("RETURN")
        !          1007:        emitlab(fname && '.END')
        !          1008:        return
        !          1009: 
        !          1010: fu_error:
        !          1011:        error("bad function definition")
        !          1012: }
        !          1013: 
        !          1014: #      the input should now contain something matching "p"
        !          1015: #      possibly surrounded by white space.  If not, fail
        !          1016: procedure expect (p) {
        !          1017: 
        !          1018:        # throw away blank lines
        !          1019:        while (linebuf ? FENCE && optblank && RPOS (0)) {
        !          1020:                if (~(linebuf = phrase()))
        !          1021:                        freturn
        !          1022:        }
        !          1023: 
        !          1024:        # try to match the given pattern, possibly preceded by white space
        !          1025:        if (linebuf ? FENCE && optblank && *p = "")
        !          1026:                return
        !          1027: 
        !          1028:        # didn't match: fail
        !          1029:        freturn
        !          1030: }
        !          1031: 
        !          1032: #      expect an identifier in the input; return it.
        !          1033: procedure getid() {
        !          1034:        if (expect (*identifier . getid))
        !          1035:                return
        !          1036:        freturn
        !          1037: }
        !          1038: 
        !          1039: #      expect a list of identifiers followed by tail
        !          1040: procedure getlist (tail) del {
        !          1041: getlist_start:
        !          1042:        if (expect(tail)) {
        !          1043:                linebuf = tail && linebuf
        !          1044:                return
        !          1045:        }
        !          1046:        if (getlist = getlist && del && getid()) {
        !          1047:                expect(',')
        !          1048:                del = ','
        !          1049:                go to getlist_start
        !          1050:        }
        !          1051:        if (expect(tail))
        !          1052:                return
        !          1053:        freturn
        !          1054: }
        !          1055: 
        !          1056: # This procedure is called once for each output statement.
        !          1057: # It maintains the correspondence between Snocone and SNOBOL4
        !          1058: # statements, which is inserted into the output for debugging.
        !          1059: procedure buildstab (stmt, file, line) desc, pad {
        !          1060:        pad = DUPL ("?", stmt - bst_stmt - 1)
        !          1061:        bst_stab = bst_stab && pad
        !          1062:        if (IDENT (file, bst_file)) {
        !          1063:                if (DIFFER(pad) || line != bst_line + 1)
        !          1064:                        desc = line
        !          1065:        } else
        !          1066:                desc = file && ":" && line
        !          1067:        bst_stab = bst_stab && desc && ","
        !          1068:        bst_stmt = stmt
        !          1069:        bst_file = file
        !          1070:        bst_line = line
        !          1071: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.